blob: af31b385980ad056ebde4c3970af9e0d744e7b95 [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 Krah1919b7e2012-03-21 18:25:23 +010037from test.support import check_warnings, import_fresh_module, TestFailed
Raymond Hettinger0aeac102004-07-05 22:53:03 +000038import random
Stefan Krah1919b7e2012-03-21 18:25:23 +010039import time
40import warnings
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000041try:
42 import threading
43except ImportError:
44 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000045
Raymond Hettingerfed52962004-07-14 15:41:57 +000046
Stefan Krah1919b7e2012-03-21 18:25:23 +010047C = import_fresh_module('decimal', fresh=['_decimal'])
48P = import_fresh_module('decimal', blocked=['_decimal'])
49orig_sys_decimal = sys.modules['decimal']
50
51# fractions module must import the correct decimal module.
52cfractions = import_fresh_module('fractions', fresh=['fractions'])
53sys.modules['decimal'] = P
54pfractions = import_fresh_module('fractions', fresh=['fractions'])
55sys.modules['decimal'] = C
56fractions = {C:cfractions, P:pfractions}
57sys.modules['decimal'] = orig_sys_decimal
58
59
60# Useful Test Constant
61Signals = {
62 C: tuple(C.getcontext().flags.keys()) if C else None,
63 P: tuple(P.getcontext().flags.keys())
64}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000065# Signals ordered with respect to precedence: when an operation
66# produces multiple signals, signals occurring later in the list
67# should be handled before those occurring earlier in the list.
Stefan Krah1919b7e2012-03-21 18:25:23 +010068OrderedSignals = {
69 C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow,
70 C.Overflow, C.DivisionByZero, C.InvalidOperation,
71 C.FloatOperation] if C else None,
72 P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow,
73 P.Overflow, P.DivisionByZero, P.InvalidOperation,
74 P.FloatOperation]
75}
76def assert_signals(cls, context, attr, expected):
77 d = getattr(context, attr)
78 cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
79
80RoundingModes = {
81 C: (C.ROUND_UP, C.ROUND_DOWN, C.ROUND_CEILING, C.ROUND_FLOOR,
82 C.ROUND_HALF_UP, C.ROUND_HALF_DOWN, C.ROUND_HALF_EVEN,
83 C.ROUND_05UP) if C else None,
84 P: (P.ROUND_UP, P.ROUND_DOWN, P.ROUND_CEILING, P.ROUND_FLOOR,
85 P.ROUND_HALF_UP, P.ROUND_HALF_DOWN, P.ROUND_HALF_EVEN,
86 P.ROUND_05UP)
87}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000088
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000089# Tests are built around these assumed context defaults.
90# test_main() restores the original context.
Stefan Krah1919b7e2012-03-21 18:25:23 +010091ORIGINAL_CONTEXT = {
92 C: C.getcontext().copy() if C else None,
93 P: P.getcontext().copy()
94}
95def init(m):
96 if not m: return
97 DefaultTestContext = m.Context(
98 prec=9, rounding=m.ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
99 )
100 m.setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +0000101
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000102TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000103if __name__ == '__main__':
104 file = sys.argv[0]
105else:
106 file = __file__
107testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +0000108directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000109
Raymond Hettinger267b8682005-03-27 10:47:39 +0000110skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000111
112# Make sure it actually raises errors when not expected and caught in flags
113# Slower, since it runs some things several times.
114EXTENDEDERRORTEST = False
115
Stefan Krah1919b7e2012-03-21 18:25:23 +0100116# Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
117EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
118requires_extra_functionality = unittest.skipUnless(
119 EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
120skip_if_extra_functionality = unittest.skipIf(
121 EXTRA_FUNCTIONALITY, "test requires regular build")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000122
123
Stefan Krah1919b7e2012-03-21 18:25:23 +0100124class IBMTestCases(unittest.TestCase):
125 """Class which tests the Decimal class against the IBM test cases."""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000126
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000127 def setUp(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100128 self.context = self.decimal.Context()
129 self.readcontext = self.decimal.Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000130 self.ignore_list = ['#']
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000131
Stefan Krah1919b7e2012-03-21 18:25:23 +0100132 # List of individual .decTest test ids that correspond to tests that
133 # we're skipping for one reason or another.
134 self.skipped_test_ids = set([
135 # Skip implementation-specific scaleb tests.
136 'scbx164',
137 'scbx165',
138
139 # For some operations (currently exp, ln, log10, power), the decNumber
140 # reference implementation imposes additional restrictions on the context
141 # and operands. These restrictions are not part of the specification;
142 # however, the effect of these restrictions does show up in some of the
143 # testcases. We skip testcases that violate these restrictions, since
144 # Decimal behaves differently from decNumber for these testcases so these
145 # testcases would otherwise fail.
146 'expx901',
147 'expx902',
148 'expx903',
149 'expx905',
150 'lnx901',
151 'lnx902',
152 'lnx903',
153 'lnx905',
154 'logx901',
155 'logx902',
156 'logx903',
157 'logx905',
158 'powx1183',
159 'powx1184',
160 'powx4001',
161 'powx4002',
162 'powx4003',
163 'powx4005',
164 'powx4008',
165 'powx4010',
166 'powx4012',
167 'powx4014',
168 ])
169
170 if self.decimal == C:
171 # status has additional Subnormal, Underflow
172 self.skipped_test_ids.add('pwsx803')
173 self.skipped_test_ids.add('pwsx805')
174 # Correct rounding (skipped for decNumber, too)
175 self.skipped_test_ids.add('powx4302')
176 self.skipped_test_ids.add('powx4303')
177 self.skipped_test_ids.add('powx4342')
178 self.skipped_test_ids.add('powx4343')
179 # http://bugs.python.org/issue7049
180 self.skipped_test_ids.add('pwmx325')
181 self.skipped_test_ids.add('pwmx326')
182
183 # Map test directives to setter functions.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000184 self.ChangeDict = {'precision' : self.change_precision,
Stefan Krah1919b7e2012-03-21 18:25:23 +0100185 'rounding' : self.change_rounding_method,
186 'maxexponent' : self.change_max_exponent,
187 'minexponent' : self.change_min_exponent,
188 'clamp' : self.change_clamp}
189
190 # Name adapter to be able to change the Decimal and Context
191 # interface without changing the test files from Cowlishaw.
192 self.NameAdapter = {'and':'logical_and',
193 'apply':'_apply',
194 'class':'number_class',
195 'comparesig':'compare_signal',
196 'comparetotal':'compare_total',
197 'comparetotmag':'compare_total_mag',
198 'copy':'copy_decimal',
199 'copyabs':'copy_abs',
200 'copynegate':'copy_negate',
201 'copysign':'copy_sign',
202 'divideint':'divide_int',
203 'invert':'logical_invert',
204 'iscanonical':'is_canonical',
205 'isfinite':'is_finite',
206 'isinfinite':'is_infinite',
207 'isnan':'is_nan',
208 'isnormal':'is_normal',
209 'isqnan':'is_qnan',
210 'issigned':'is_signed',
211 'issnan':'is_snan',
212 'issubnormal':'is_subnormal',
213 'iszero':'is_zero',
214 'maxmag':'max_mag',
215 'minmag':'min_mag',
216 'nextminus':'next_minus',
217 'nextplus':'next_plus',
218 'nexttoward':'next_toward',
219 'or':'logical_or',
220 'reduce':'normalize',
221 'remaindernear':'remainder_near',
222 'samequantum':'same_quantum',
223 'squareroot':'sqrt',
224 'toeng':'to_eng_string',
225 'tointegral':'to_integral_value',
226 'tointegralx':'to_integral_exact',
227 'tosci':'to_sci_string',
228 'xor':'logical_xor'}
229
230 # Map test-case names to roundings.
231 self.RoundingDict = {'ceiling' : self.decimal.ROUND_CEILING,
232 'down' : self.decimal.ROUND_DOWN,
233 'floor' : self.decimal.ROUND_FLOOR,
234 'half_down' : self.decimal.ROUND_HALF_DOWN,
235 'half_even' : self.decimal.ROUND_HALF_EVEN,
236 'half_up' : self.decimal.ROUND_HALF_UP,
237 'up' : self.decimal.ROUND_UP,
238 '05up' : self.decimal.ROUND_05UP}
239
240 # Map the test cases' error names to the actual errors.
241 self.ErrorNames = {'clamped' : self.decimal.Clamped,
242 'conversion_syntax' : self.decimal.InvalidOperation,
243 'division_by_zero' : self.decimal.DivisionByZero,
244 'division_impossible' : self.decimal.InvalidOperation,
245 'division_undefined' : self.decimal.InvalidOperation,
246 'inexact' : self.decimal.Inexact,
247 'invalid_context' : self.decimal.InvalidOperation,
248 'invalid_operation' : self.decimal.InvalidOperation,
249 'overflow' : self.decimal.Overflow,
250 'rounded' : self.decimal.Rounded,
251 'subnormal' : self.decimal.Subnormal,
252 'underflow' : self.decimal.Underflow}
253
254 # The following functions return True/False rather than a
255 # Decimal instance.
256 self.LogicalFunctions = ('is_canonical',
257 'is_finite',
258 'is_infinite',
259 'is_nan',
260 'is_normal',
261 'is_qnan',
262 'is_signed',
263 'is_snan',
264 'is_subnormal',
265 'is_zero',
266 'same_quantum')
267
268 def read_unlimited(self, v, context):
269 """Work around the limitations of the 32-bit _decimal version. The
270 guaranteed maximum values for prec, Emax etc. are 425000000,
271 but higher values usually work, except for rare corner cases.
272 In particular, all of the IBM tests pass with maximum values
273 of 1070000000."""
274 if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
275 self.readcontext._unsafe_setprec(1070000000)
276 self.readcontext._unsafe_setemax(1070000000)
277 self.readcontext._unsafe_setemin(-1070000000)
278 return self.readcontext.create_decimal(v)
279 else:
280 return self.decimal.Decimal(v, context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000281
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000282 def eval_file(self, file):
283 global skip_expected
284 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000285 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000286 return
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000287 with open(file) as f:
288 for line in f:
289 line = line.replace('\r\n', '').replace('\n', '')
290 #print line
291 try:
292 t = self.eval_line(line)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100293 except self.decimal.DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200294 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000295 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000296
297 return
298
299 def eval_line(self, s):
300 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
301 s = (s.split('->')[0] + '->' +
302 s.split('->')[1].split('--')[0]).strip()
303 else:
304 s = s.split('--')[0].strip()
305
306 for ignore in self.ignore_list:
307 if s.find(ignore) >= 0:
308 #print s.split()[0], 'NotImplemented--', ignore
309 return
310 if not s:
311 return
312 elif ':' in s:
313 return self.eval_directive(s)
314 else:
315 return self.eval_equation(s)
316
317 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000318 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000319 if funct == 'rounding':
Stefan Krah1919b7e2012-03-21 18:25:23 +0100320 value = self.RoundingDict[value]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000321 else:
322 try:
323 value = int(value)
324 except ValueError:
325 pass
326
Stefan Krah1919b7e2012-03-21 18:25:23 +0100327 funct = self.ChangeDict.get(funct, (lambda *args: None))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000328 funct(value)
329
330 def eval_equation(self, s):
Raymond Hettingered20ad82004-09-04 20:09:13 +0000331
332 if not TEST_ALL and random.random() < 0.90:
333 return
334
Stefan Krah1919b7e2012-03-21 18:25:23 +0100335 self.context.clear_flags()
336
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000337 try:
338 Sides = s.split('->')
339 L = Sides[0].strip().split()
340 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000341 if DEBUG:
342 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000343 funct = L[1].lower()
344 valstemp = L[2:]
345 L = Sides[1].strip().split()
346 ans = L[0]
347 exceptions = L[1:]
348 except (TypeError, AttributeError, IndexError):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100349 raise self.decimal.InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000350 def FixQuotes(val):
351 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
352 val = val.replace("'", '').replace('"', '')
353 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
354 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000355
Stefan Krah1919b7e2012-03-21 18:25:23 +0100356 if id in self.skipped_test_ids:
Mark Dickinson8a546532009-10-08 16:30:38 +0000357 return
358
Stefan Krah1919b7e2012-03-21 18:25:23 +0100359 fname = self.NameAdapter.get(funct, funct)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000360 if fname == 'rescale':
361 return
362 funct = getattr(self.context, fname)
363 vals = []
364 conglomerate = ''
365 quote = 0
Stefan Krah1919b7e2012-03-21 18:25:23 +0100366 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000367
Stefan Krah1919b7e2012-03-21 18:25:23 +0100368 for exception in Signals[self.decimal]:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000369 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000370 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000371 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000372 for i, val in enumerate(valstemp):
373 if val.count("'") % 2 == 1:
374 quote = 1 - quote
375 if quote:
376 conglomerate = conglomerate + ' ' + val
377 continue
378 else:
379 val = conglomerate + val
380 conglomerate = ''
381 v = FixQuotes(val)
382 if fname in ('to_sci_string', 'to_eng_string'):
383 if EXTENDEDERRORTEST:
384 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000385 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000386 try:
387 funct(self.context.create_decimal(v))
388 except error:
389 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100390 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000391 self.fail("Raised %s in %s when %s disabled" % \
392 (e, s, error))
393 else:
394 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000395 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000396 v = self.context.create_decimal(v)
397 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +0100398 v = self.read_unlimited(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000399 vals.append(v)
400
401 ans = FixQuotes(ans)
402
403 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
404 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000405 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000406 try:
407 funct(*vals)
408 except error:
409 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100410 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000411 self.fail("Raised %s in %s when %s disabled" % \
412 (e, s, error))
413 else:
414 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000415 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000416
417 # as above, but add traps cumulatively, to check precedence
Stefan Krah1919b7e2012-03-21 18:25:23 +0100418 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions]
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000419 for error in ordered_errors:
420 self.context.traps[error] = 1
421 try:
422 funct(*vals)
423 except error:
424 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100425 except Signals[self.decimal] as e:
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000426 self.fail("Raised %s in %s; expected %s" %
427 (type(e), s, error))
428 else:
429 self.fail("Did not raise %s in %s" % (error, s))
430 # reset traps
431 for error in ordered_errors:
432 self.context.traps[error] = 0
433
434
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000435 if DEBUG:
436 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000437 try:
438 result = str(funct(*vals))
Stefan Krah1919b7e2012-03-21 18:25:23 +0100439 if fname in self.LogicalFunctions:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000440 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Stefan Krah1919b7e2012-03-21 18:25:23 +0100441 except Signals[self.decimal] as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000442 self.fail("Raised %s in %s" % (error, s))
443 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000444 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000445 raise
446
447 myexceptions = self.getexceptions()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000448
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000449 myexceptions.sort(key=repr)
450 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000451
452 self.assertEqual(result, ans,
453 'Incorrect answer for ' + s + ' -- got ' + result)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100454
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000455 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000456 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000457 return
458
459 def getexceptions(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100460 return [e for e in Signals[self.decimal] if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000461
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000462 def change_precision(self, prec):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100463 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
464 self.context._unsafe_setprec(prec)
465 else:
466 self.context.prec = prec
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000467 def change_rounding_method(self, rounding):
468 self.context.rounding = rounding
469 def change_min_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100470 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
471 self.context._unsafe_setemin(exp)
472 else:
473 self.context.Emin = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000474 def change_max_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100475 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
476 self.context._unsafe_setemax(exp)
477 else:
478 self.context.Emax = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000479 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000480 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000481
Stefan Krah1919b7e2012-03-21 18:25:23 +0100482class CIBMTestCases(IBMTestCases):
483 decimal = C
484class PyIBMTestCases(IBMTestCases):
485 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000486
487# The following classes test the behaviour of Decimal according to PEP 327
488
Stefan Krah1919b7e2012-03-21 18:25:23 +0100489class ExplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000490 '''Unit tests for Explicit Construction cases of Decimal.'''
491
492 def test_explicit_empty(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100493 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000494 self.assertEqual(Decimal(), Decimal("0"))
495
496 def test_explicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100497 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000498 self.assertRaises(TypeError, Decimal, None)
499
500 def test_explicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100501 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000502
503 #positive
504 d = Decimal(45)
505 self.assertEqual(str(d), '45')
506
507 #very large positive
508 d = Decimal(500000123)
509 self.assertEqual(str(d), '500000123')
510
511 #negative
512 d = Decimal(-45)
513 self.assertEqual(str(d), '-45')
514
515 #zero
516 d = Decimal(0)
517 self.assertEqual(str(d), '0')
518
Stefan Krah1919b7e2012-03-21 18:25:23 +0100519 # single word longs
520 for n in range(0, 32):
521 for sign in (-1, 1):
522 for x in range(-5, 5):
523 i = sign * (2**n + x)
524 d = Decimal(i)
525 self.assertEqual(str(d), str(i))
526
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000527 def test_explicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100528 Decimal = self.decimal.Decimal
529 InvalidOperation = self.decimal.InvalidOperation
530 localcontext = self.decimal.localcontext
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000531
532 #empty
533 self.assertEqual(str(Decimal('')), 'NaN')
534
535 #int
536 self.assertEqual(str(Decimal('45')), '45')
537
538 #float
539 self.assertEqual(str(Decimal('45.34')), '45.34')
540
541 #engineer notation
542 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
543
544 #just not a number
545 self.assertEqual(str(Decimal('ugly')), 'NaN')
546
Christian Heimesa62da1d2008-01-12 19:39:10 +0000547 #leading and trailing whitespace permitted
548 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
549 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
Stefan Krah1919b7e2012-03-21 18:25:23 +0100550 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
551
552 # unicode whitespace
553 for lead in ["", ' ', '\u00a0', '\u205f']:
554 for trail in ["", ' ', '\u00a0', '\u205f']:
555 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
556 '9.311E+28')
557
558 with localcontext() as c:
559 c.traps[InvalidOperation] = True
560 # Invalid string
561 self.assertRaises(InvalidOperation, Decimal, "xyz")
562 # Two arguments max
563 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
564
565 # space within the numeric part
566 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
567 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
568
569 # unicode whitespace
570 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
571 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
572
573 # embedded NUL
574 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
575
Christian Heimesa62da1d2008-01-12 19:39:10 +0000576
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000577 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100578 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000579
580 #zero
581 d = Decimal( (0, (0,), 0) )
582 self.assertEqual(str(d), '0')
583
584 #int
585 d = Decimal( (1, (4, 5), 0) )
586 self.assertEqual(str(d), '-45')
587
588 #float
589 d = Decimal( (0, (4, 5, 3, 4), -2) )
590 self.assertEqual(str(d), '45.34')
591
592 #weird
593 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
594 self.assertEqual(str(d), '-4.34913534E-17')
595
Stefan Krah1919b7e2012-03-21 18:25:23 +0100596 #inf
597 d = Decimal( (0, (), "F") )
598 self.assertEqual(str(d), 'Infinity')
599
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000600 #wrong number of items
601 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
602
603 #bad sign
604 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000605 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
606 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000607
608 #bad exp
609 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000610 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
611 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000612
613 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100614 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000615 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
616 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000617 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000618 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000619
Stefan Krah1919b7e2012-03-21 18:25:23 +0100620 def test_explicit_from_list(self):
621 Decimal = self.decimal.Decimal
622
623 d = Decimal([0, [0], 0])
624 self.assertEqual(str(d), '0')
625
626 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
627 self.assertEqual(str(d), '-4.34913534E-17')
628
629 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
630 self.assertEqual(str(d), '-4.34913534E-17')
631
632 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
633 self.assertEqual(str(d), '-4.34913534E-17')
634
Antoine Pitrou503ab332010-03-30 18:56:19 +0000635 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100636 Decimal = self.decimal.Decimal
637
Antoine Pitrou503ab332010-03-30 18:56:19 +0000638 self.assertIs(bool(Decimal(0)), False)
639 self.assertIs(bool(Decimal(1)), True)
640 self.assertEqual(Decimal(False), Decimal(0))
641 self.assertEqual(Decimal(True), Decimal(1))
642
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000643 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100644 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000645
646 #positive
647 d = Decimal(45)
648 e = Decimal(d)
649 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000650
651 #very large positive
652 d = Decimal(500000123)
653 e = Decimal(d)
654 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000655
656 #negative
657 d = Decimal(-45)
658 e = Decimal(d)
659 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000660
661 #zero
662 d = Decimal(0)
663 e = Decimal(d)
664 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000665
Raymond Hettinger96798592010-04-02 16:58:27 +0000666 @requires_IEEE_754
667 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100668
669 Decimal = self.decimal.Decimal
670
Raymond Hettinger96798592010-04-02 16:58:27 +0000671 r = Decimal(0.1)
672 self.assertEqual(type(r), Decimal)
673 self.assertEqual(str(r),
674 '0.1000000000000000055511151231257827021181583404541015625')
675 self.assertTrue(Decimal(float('nan')).is_qnan())
676 self.assertTrue(Decimal(float('inf')).is_infinite())
677 self.assertTrue(Decimal(float('-inf')).is_infinite())
678 self.assertEqual(str(Decimal(float('nan'))),
679 str(Decimal('NaN')))
680 self.assertEqual(str(Decimal(float('inf'))),
681 str(Decimal('Infinity')))
682 self.assertEqual(str(Decimal(float('-inf'))),
683 str(Decimal('-Infinity')))
684 self.assertEqual(str(Decimal(float('-0.0'))),
685 str(Decimal('-0')))
686 for i in range(200):
687 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
688 self.assertEqual(x, float(Decimal(x))) # roundtrip
689
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000690 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100691 Decimal = self.decimal.Decimal
692 InvalidOperation = self.decimal.InvalidOperation
693 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000694
Stefan Krah1919b7e2012-03-21 18:25:23 +0100695 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000696 nc.prec = 3
697
698 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000699 d = Decimal()
700 self.assertEqual(str(d), '0')
701 d = nc.create_decimal()
702 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000703
704 # from None
705 self.assertRaises(TypeError, nc.create_decimal, None)
706
707 # from int
708 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000709 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000710 self.assertEqual(nc.create_decimal(45678),
711 nc.create_decimal('457E+2'))
712
713 # from string
714 d = Decimal('456789')
715 self.assertEqual(str(d), '456789')
716 d = nc.create_decimal('456789')
717 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000718 # leading and trailing whitespace should result in a NaN;
719 # spaces are already checked in Cowlishaw's test-suite, so
720 # here we just check that a trailing newline results in a NaN
721 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000722
723 # from tuples
724 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
725 self.assertEqual(str(d), '-4.34913534E-17')
726 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
727 self.assertEqual(str(d), '-4.35E-17')
728
729 # from Decimal
730 prevdec = Decimal(500000123)
731 d = Decimal(prevdec)
732 self.assertEqual(str(d), '500000123')
733 d = nc.create_decimal(prevdec)
734 self.assertEqual(str(d), '5.00E+8')
735
Stefan Krah1919b7e2012-03-21 18:25:23 +0100736 # more integers
737 nc.prec = 28
738 nc.traps[InvalidOperation] = True
739
740 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
741 2**31-1, 2**31, 2**63-1, 2**63]:
742 d = nc.create_decimal(v)
743 self.assertTrue(isinstance(d, Decimal))
744 self.assertEqual(int(d), v)
745
746 nc.prec = 3
747 nc.traps[Rounded] = True
748 self.assertRaises(Rounded, nc.create_decimal, 1234)
749
750 # from string
751 nc.prec = 28
752 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
753 self.assertEqual(str(nc.create_decimal('45')), '45')
754 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
755 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
756
757 # invalid arguments
758 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
759 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
760 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
761
762 # too many NaN payload digits
763 nc.prec = 3
764 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
765 self.assertRaises(InvalidOperation, nc.create_decimal,
766 Decimal('NaN12345'))
767
768 nc.traps[InvalidOperation] = False
769 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
770 self.assertTrue(nc.flags[InvalidOperation])
771
772 nc.flags[InvalidOperation] = False
773 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
774 self.assertTrue(nc.flags[InvalidOperation])
775
776 def test_explicit_context_create_from_float(self):
777
778 Decimal = self.decimal.Decimal
779
780 nc = self.decimal.Context()
781 r = nc.create_decimal(0.1)
782 self.assertEqual(type(r), Decimal)
783 self.assertEqual(str(r), '0.1000000000000000055511151231')
784 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
785 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
786 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
787 self.assertEqual(str(nc.create_decimal(float('nan'))),
788 str(nc.create_decimal('NaN')))
789 self.assertEqual(str(nc.create_decimal(float('inf'))),
790 str(nc.create_decimal('Infinity')))
791 self.assertEqual(str(nc.create_decimal(float('-inf'))),
792 str(nc.create_decimal('-Infinity')))
793 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
794 str(nc.create_decimal('-0')))
795 nc.prec = 100
796 for i in range(200):
797 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
798 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
799
Mark Dickinson345adc42009-08-02 10:14:23 +0000800 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100801 Decimal = self.decimal.Decimal
802
Mark Dickinson345adc42009-08-02 10:14:23 +0000803 test_values = {
804 '\uff11': '1',
805 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
806 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
807 }
808 for input, expected in test_values.items():
809 self.assertEqual(str(Decimal(input)), expected)
810
Stefan Krah1919b7e2012-03-21 18:25:23 +0100811class CExplicitConstructionTest(ExplicitConstructionTest):
812 decimal = C
813class PyExplicitConstructionTest(ExplicitConstructionTest):
814 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000815
Stefan Krah1919b7e2012-03-21 18:25:23 +0100816class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000817 '''Unit tests for Implicit Construction cases of Decimal.'''
818
819 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100820 Decimal = self.decimal.Decimal
821 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000822
823 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100824 Decimal = self.decimal.Decimal
825
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000826 #normal
827 self.assertEqual(str(Decimal(5) + 45), '50')
828 #exceeding precision
829 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
830
831 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100832 Decimal = self.decimal.Decimal
833 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000834
835 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100836 Decimal = self.decimal.Decimal
837 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000838
839 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100840 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000841 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
842
Raymond Hettinger267b8682005-03-27 10:47:39 +0000843 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100844 Decimal = self.decimal.Decimal
845
Raymond Hettinger267b8682005-03-27 10:47:39 +0000846 # Allow other classes to be trained to interact with Decimals
847 class E:
848 def __divmod__(self, other):
849 return 'divmod ' + str(other)
850 def __rdivmod__(self, other):
851 return str(other) + ' rdivmod'
852 def __lt__(self, other):
853 return 'lt ' + str(other)
854 def __gt__(self, other):
855 return 'gt ' + str(other)
856 def __le__(self, other):
857 return 'le ' + str(other)
858 def __ge__(self, other):
859 return 'ge ' + str(other)
860 def __eq__(self, other):
861 return 'eq ' + str(other)
862 def __ne__(self, other):
863 return 'ne ' + str(other)
864
865 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
866 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
867 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
868 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
869 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
870 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
871 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
872 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
873
874 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000875 oplist = [
876 ('+', '__add__', '__radd__'),
877 ('-', '__sub__', '__rsub__'),
878 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000879 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000880 ('%', '__mod__', '__rmod__'),
881 ('//', '__floordiv__', '__rfloordiv__'),
882 ('**', '__pow__', '__rpow__')
883 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000884
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000885 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000886 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
887 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
888 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
889 'str' + lop + '10')
890 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
891 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000892
Stefan Krah1919b7e2012-03-21 18:25:23 +0100893class CImplicitConstructionTest(ImplicitConstructionTest):
894 decimal = C
895class PyImplicitConstructionTest(ImplicitConstructionTest):
896 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000897
Stefan Krah1919b7e2012-03-21 18:25:23 +0100898class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000899 '''Unit tests for the format function.'''
900 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100901 Decimal = self.decimal.Decimal
902
Christian Heimesf16baeb2008-02-29 14:57:44 +0000903 # triples giving a format, a Decimal, and the expected result
904 test_values = [
905 ('e', '0E-15', '0e-15'),
906 ('e', '2.3E-15', '2.3e-15'),
907 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
908 ('e', '2.30000E-15', '2.30000e-15'),
909 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
910 ('e', '1.5', '1.5e+0'),
911 ('e', '0.15', '1.5e-1'),
912 ('e', '0.015', '1.5e-2'),
913 ('e', '0.0000000000015', '1.5e-12'),
914 ('e', '15.0', '1.50e+1'),
915 ('e', '-15', '-1.5e+1'),
916 ('e', '0', '0e+0'),
917 ('e', '0E1', '0e+1'),
918 ('e', '0.0', '0e-1'),
919 ('e', '0.00', '0e-2'),
920 ('.6e', '0E-15', '0.000000e-9'),
921 ('.6e', '0', '0.000000e+6'),
922 ('.6e', '9.999999', '9.999999e+0'),
923 ('.6e', '9.9999999', '1.000000e+1'),
924 ('.6e', '-1.23e5', '-1.230000e+5'),
925 ('.6e', '1.23456789e-3', '1.234568e-3'),
926 ('f', '0', '0'),
927 ('f', '0.0', '0.0'),
928 ('f', '0E-2', '0.00'),
929 ('f', '0.00E-8', '0.0000000000'),
930 ('f', '0E1', '0'), # loses exponent information
931 ('f', '3.2E1', '32'),
932 ('f', '3.2E2', '320'),
933 ('f', '3.20E2', '320'),
934 ('f', '3.200E2', '320.0'),
935 ('f', '3.2E-6', '0.0000032'),
936 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
937 ('.6f', '0E1', '0.000000'),
938 ('.6f', '0', '0.000000'),
939 ('.0f', '0', '0'), # no decimal point
940 ('.0f', '0e-2', '0'),
941 ('.0f', '3.14159265', '3'),
942 ('.1f', '3.14159265', '3.1'),
943 ('.4f', '3.14159265', '3.1416'),
944 ('.6f', '3.14159265', '3.141593'),
945 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
946 ('.8f', '3.14159265', '3.14159265'),
947 ('.9f', '3.14159265', '3.141592650'),
948
949 ('g', '0', '0'),
950 ('g', '0.0', '0.0'),
951 ('g', '0E1', '0e+1'),
952 ('G', '0E1', '0E+1'),
953 ('g', '0E-5', '0.00000'),
954 ('g', '0E-6', '0.000000'),
955 ('g', '0E-7', '0e-7'),
956 ('g', '-0E2', '-0e+2'),
957 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100958 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000959 ('.1g', '3.14159265', '3'),
960 ('.2g', '3.14159265', '3.1'),
961 ('.5g', '3.14159265', '3.1416'),
962 ('.7g', '3.14159265', '3.141593'),
963 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
964 ('.9g', '3.14159265', '3.14159265'),
965 ('.10g', '3.14159265', '3.14159265'), # don't pad
966
967 ('%', '0E1', '0%'),
968 ('%', '0E0', '0%'),
969 ('%', '0E-1', '0%'),
970 ('%', '0E-2', '0%'),
971 ('%', '0E-3', '0.0%'),
972 ('%', '0E-4', '0.00%'),
973
974 ('.3%', '0', '0.000%'), # all zeros treated equally
975 ('.3%', '0E10', '0.000%'),
976 ('.3%', '0E-10', '0.000%'),
977 ('.3%', '2.34', '234.000%'),
978 ('.3%', '1.234567', '123.457%'),
979 ('.0%', '1.23', '123%'),
980
981 ('e', 'NaN', 'NaN'),
982 ('f', '-NaN123', '-NaN123'),
983 ('+g', 'NaN456', '+NaN456'),
984 ('.3e', 'Inf', 'Infinity'),
985 ('.16f', '-Inf', '-Infinity'),
986 ('.0g', '-sNaN', '-sNaN'),
987
988 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000989
Mark Dickinson79f52032009-03-17 23:12:51 +0000990 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000991 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000992 ('<6', '123', '123 '),
993 ('>6', '123', ' 123'),
994 ('^6', '123', ' 123 '),
995 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000996 ('#<10', 'NaN', 'NaN#######'),
997 ('#<10', '-4.3', '-4.3######'),
998 ('#<+10', '0.0130', '+0.0130###'),
999 ('#< 10', '0.0130', ' 0.0130###'),
1000 ('@>10', '-Inf', '@-Infinity'),
1001 ('#>5', '-Inf', '-Infinity'),
1002 ('?^5', '123', '?123?'),
1003 ('%^6', '123', '%123%%'),
1004 (' ^6', '-45.6', '-45.6 '),
1005 ('/=10', '-45.6', '-/////45.6'),
1006 ('/=+10', '45.6', '+/////45.6'),
1007 ('/= 10', '45.6', ' /////45.6'),
1008
1009 # thousands separator
1010 (',', '1234567', '1,234,567'),
1011 (',', '123456', '123,456'),
1012 (',', '12345', '12,345'),
1013 (',', '1234', '1,234'),
1014 (',', '123', '123'),
1015 (',', '12', '12'),
1016 (',', '1', '1'),
1017 (',', '0', '0'),
1018 (',', '-1234567', '-1,234,567'),
1019 (',', '-123456', '-123,456'),
1020 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001021 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001022 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1023 ('+08,', '123456', '+123,456'), # but not if there's a sign
1024 (' 08,', '123456', ' 123,456'),
1025 ('08,', '-123456', '-123,456'),
1026 ('+09,', '123456', '+0,123,456'),
1027 # ... with fractional part...
1028 ('07,', '1234.56', '1,234.56'),
1029 ('08,', '1234.56', '1,234.56'),
1030 ('09,', '1234.56', '01,234.56'),
1031 ('010,', '1234.56', '001,234.56'),
1032 ('011,', '1234.56', '0,001,234.56'),
1033 ('012,', '1234.56', '0,001,234.56'),
1034 ('08,.1f', '1234.5', '01,234.5'),
1035 # no thousands separators in fraction part
1036 (',', '1.23456789', '1.23456789'),
1037 (',%', '123.456789', '12,345.6789%'),
1038 (',e', '123456', '1.23456e+5'),
1039 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001040
1041 # issue 6850
1042 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001043 ]
1044 for fmt, d, result in test_values:
1045 self.assertEqual(format(Decimal(d), fmt), result)
1046
Stefan Krah1919b7e2012-03-21 18:25:23 +01001047 # bytes format argument
1048 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1049
Mark Dickinson79f52032009-03-17 23:12:51 +00001050 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001051 Decimal = self.decimal.Decimal
1052
Mark Dickinson79f52032009-03-17 23:12:51 +00001053 try:
1054 from locale import CHAR_MAX
1055 except ImportError:
1056 return
1057
Stefan Krah1919b7e2012-03-21 18:25:23 +01001058 def make_grouping(lst):
1059 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1060
1061 def get_fmt(x, override=None, fmt='n'):
1062 if self.decimal == C:
1063 return Decimal(x).__format__(fmt, override)
1064 else:
1065 return Decimal(x).__format__(fmt, _localeconv=override)
1066
Mark Dickinson79f52032009-03-17 23:12:51 +00001067 # Set up some localeconv-like dictionaries
1068 en_US = {
1069 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001070 'grouping' : make_grouping([3, 3, 0]),
1071 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001072 }
1073
1074 fr_FR = {
1075 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001076 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001077 'thousands_sep' : ''
1078 }
1079
1080 ru_RU = {
1081 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001082 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001083 'thousands_sep' : ' '
1084 }
1085
1086 crazy = {
1087 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001088 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001089 'thousands_sep' : '-'
1090 }
1091
Stefan Krah1919b7e2012-03-21 18:25:23 +01001092 dotsep_wide = {
1093 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1094 'grouping': make_grouping([3, 3, 0]),
1095 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1096 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001097
1098 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1099 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1100 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1101 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1102
1103 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1104 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1105 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1106 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1107
1108 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1109 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1110 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1111 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1112
Mark Dickinson7303b592009-03-18 08:25:36 +00001113 # zero padding
1114 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1115 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1116 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1117 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1118
1119 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1120 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1121 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1122 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1123 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1124 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1125
1126 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1127 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1128 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1129 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1130 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1131 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1132 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1133 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1134
Stefan Krah1919b7e2012-03-21 18:25:23 +01001135 # wide char separator and decimal point
1136 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1137 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001138
Stefan Krah1919b7e2012-03-21 18:25:23 +01001139 def test_wide_char_separator_decimal_point(self):
1140 # locale with wide char separator and decimal point
1141 Decimal = self.decimal.Decimal
1142
1143 try:
1144 locale.setlocale(locale.LC_ALL, 'ps_AF')
1145 except locale.Error:
1146 return
1147
1148 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1149 '100\u066c000\u066c000\u066b123')
1150 locale.resetlocale()
1151
1152class CFormatTest(FormatTest):
1153 decimal = C
1154class PyFormatTest(FormatTest):
1155 decimal = P
1156
1157class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001158 '''Unit tests for all arithmetic operators, binary and unary.'''
1159
1160 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001161 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001162
1163 d1 = Decimal('-11.1')
1164 d2 = Decimal('22.2')
1165
1166 #two Decimals
1167 self.assertEqual(d1+d2, Decimal('11.1'))
1168 self.assertEqual(d2+d1, Decimal('11.1'))
1169
1170 #with other type, left
1171 c = d1 + 5
1172 self.assertEqual(c, Decimal('-6.1'))
1173 self.assertEqual(type(c), type(d1))
1174
1175 #with other type, right
1176 c = 5 + d1
1177 self.assertEqual(c, Decimal('-6.1'))
1178 self.assertEqual(type(c), type(d1))
1179
1180 #inline with decimal
1181 d1 += d2
1182 self.assertEqual(d1, Decimal('11.1'))
1183
1184 #inline with other type
1185 d1 += 5
1186 self.assertEqual(d1, Decimal('16.1'))
1187
1188 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001189 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001190
1191 d1 = Decimal('-11.1')
1192 d2 = Decimal('22.2')
1193
1194 #two Decimals
1195 self.assertEqual(d1-d2, Decimal('-33.3'))
1196 self.assertEqual(d2-d1, Decimal('33.3'))
1197
1198 #with other type, left
1199 c = d1 - 5
1200 self.assertEqual(c, Decimal('-16.1'))
1201 self.assertEqual(type(c), type(d1))
1202
1203 #with other type, right
1204 c = 5 - d1
1205 self.assertEqual(c, Decimal('16.1'))
1206 self.assertEqual(type(c), type(d1))
1207
1208 #inline with decimal
1209 d1 -= d2
1210 self.assertEqual(d1, Decimal('-33.3'))
1211
1212 #inline with other type
1213 d1 -= 5
1214 self.assertEqual(d1, Decimal('-38.3'))
1215
1216 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001217 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001218
1219 d1 = Decimal('-5')
1220 d2 = Decimal('3')
1221
1222 #two Decimals
1223 self.assertEqual(d1*d2, Decimal('-15'))
1224 self.assertEqual(d2*d1, Decimal('-15'))
1225
1226 #with other type, left
1227 c = d1 * 5
1228 self.assertEqual(c, Decimal('-25'))
1229 self.assertEqual(type(c), type(d1))
1230
1231 #with other type, right
1232 c = 5 * d1
1233 self.assertEqual(c, Decimal('-25'))
1234 self.assertEqual(type(c), type(d1))
1235
1236 #inline with decimal
1237 d1 *= d2
1238 self.assertEqual(d1, Decimal('-15'))
1239
1240 #inline with other type
1241 d1 *= 5
1242 self.assertEqual(d1, Decimal('-75'))
1243
1244 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001245 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001246
1247 d1 = Decimal('-5')
1248 d2 = Decimal('2')
1249
1250 #two Decimals
1251 self.assertEqual(d1/d2, Decimal('-2.5'))
1252 self.assertEqual(d2/d1, Decimal('-0.4'))
1253
1254 #with other type, left
1255 c = d1 / 4
1256 self.assertEqual(c, Decimal('-1.25'))
1257 self.assertEqual(type(c), type(d1))
1258
1259 #with other type, right
1260 c = 4 / d1
1261 self.assertEqual(c, Decimal('-0.8'))
1262 self.assertEqual(type(c), type(d1))
1263
1264 #inline with decimal
1265 d1 /= d2
1266 self.assertEqual(d1, Decimal('-2.5'))
1267
1268 #inline with other type
1269 d1 /= 4
1270 self.assertEqual(d1, Decimal('-0.625'))
1271
1272 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001273 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001274
1275 d1 = Decimal('5')
1276 d2 = Decimal('2')
1277
1278 #two Decimals
1279 self.assertEqual(d1//d2, Decimal('2'))
1280 self.assertEqual(d2//d1, Decimal('0'))
1281
1282 #with other type, left
1283 c = d1 // 4
1284 self.assertEqual(c, Decimal('1'))
1285 self.assertEqual(type(c), type(d1))
1286
1287 #with other type, right
1288 c = 7 // d1
1289 self.assertEqual(c, Decimal('1'))
1290 self.assertEqual(type(c), type(d1))
1291
1292 #inline with decimal
1293 d1 //= d2
1294 self.assertEqual(d1, Decimal('2'))
1295
1296 #inline with other type
1297 d1 //= 2
1298 self.assertEqual(d1, Decimal('1'))
1299
1300 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001301 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001302
1303 d1 = Decimal('5')
1304 d2 = Decimal('2')
1305
1306 #two Decimals
1307 self.assertEqual(d1**d2, Decimal('25'))
1308 self.assertEqual(d2**d1, Decimal('32'))
1309
1310 #with other type, left
1311 c = d1 ** 4
1312 self.assertEqual(c, Decimal('625'))
1313 self.assertEqual(type(c), type(d1))
1314
1315 #with other type, right
1316 c = 7 ** d1
1317 self.assertEqual(c, Decimal('16807'))
1318 self.assertEqual(type(c), type(d1))
1319
1320 #inline with decimal
1321 d1 **= d2
1322 self.assertEqual(d1, Decimal('25'))
1323
1324 #inline with other type
1325 d1 **= 4
1326 self.assertEqual(d1, Decimal('390625'))
1327
1328 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001329 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001330
1331 d1 = Decimal('5')
1332 d2 = Decimal('2')
1333
1334 #two Decimals
1335 self.assertEqual(d1%d2, Decimal('1'))
1336 self.assertEqual(d2%d1, Decimal('2'))
1337
1338 #with other type, left
1339 c = d1 % 4
1340 self.assertEqual(c, Decimal('1'))
1341 self.assertEqual(type(c), type(d1))
1342
1343 #with other type, right
1344 c = 7 % d1
1345 self.assertEqual(c, Decimal('2'))
1346 self.assertEqual(type(c), type(d1))
1347
1348 #inline with decimal
1349 d1 %= d2
1350 self.assertEqual(d1, Decimal('1'))
1351
1352 #inline with other type
1353 d1 %= 4
1354 self.assertEqual(d1, Decimal('1'))
1355
1356 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001357 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001358
1359 d1 = Decimal('5')
1360 d2 = Decimal('2')
1361
1362 #two Decimals
1363 (p, q) = divmod(d1, d2)
1364 self.assertEqual(p, Decimal('2'))
1365 self.assertEqual(q, Decimal('1'))
1366 self.assertEqual(type(p), type(d1))
1367 self.assertEqual(type(q), type(d1))
1368
1369 #with other type, left
1370 (p, q) = divmod(d1, 4)
1371 self.assertEqual(p, Decimal('1'))
1372 self.assertEqual(q, Decimal('1'))
1373 self.assertEqual(type(p), type(d1))
1374 self.assertEqual(type(q), type(d1))
1375
1376 #with other type, right
1377 (p, q) = divmod(7, d1)
1378 self.assertEqual(p, Decimal('1'))
1379 self.assertEqual(q, Decimal('2'))
1380 self.assertEqual(type(p), type(d1))
1381 self.assertEqual(type(q), type(d1))
1382
1383 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001384 Decimal = self.decimal.Decimal
1385
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001386 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1387 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1388 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1389
Christian Heimes77c02eb2008-02-09 02:18:51 +00001390 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001391 # comparisons involving signaling nans signal InvalidOperation
1392
1393 # order comparisons (<, <=, >, >=) involving only quiet nans
1394 # also signal InvalidOperation
1395
1396 # equality comparisons (==, !=) involving only quiet nans
1397 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001398 Decimal = self.decimal.Decimal
1399 InvalidOperation = self.decimal.InvalidOperation
1400 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001401
Christian Heimes77c02eb2008-02-09 02:18:51 +00001402 n = Decimal('NaN')
1403 s = Decimal('sNaN')
1404 i = Decimal('Inf')
1405 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001406
1407 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1408 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1409 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1410 equality_ops = operator.eq, operator.ne
1411
1412 # results when InvalidOperation is not trapped
1413 for x, y in qnan_pairs + snan_pairs:
1414 for op in order_ops + equality_ops:
1415 got = op(x, y)
1416 expected = True if op is operator.ne else False
1417 self.assertIs(expected, got,
1418 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1419 "got {4!r}".format(
1420 expected, op.__name__, x, y, got))
1421
1422 # repeat the above, but this time trap the InvalidOperation
1423 with localcontext() as ctx:
1424 ctx.traps[InvalidOperation] = 1
1425
1426 for x, y in qnan_pairs:
1427 for op in equality_ops:
1428 got = op(x, y)
1429 expected = True if op is operator.ne else False
1430 self.assertIs(expected, got,
1431 "expected {0!r} for "
1432 "operator.{1}({2!r}, {3!r}); "
1433 "got {4!r}".format(
1434 expected, op.__name__, x, y, got))
1435
1436 for x, y in snan_pairs:
1437 for op in equality_ops:
1438 self.assertRaises(InvalidOperation, operator.eq, x, y)
1439 self.assertRaises(InvalidOperation, operator.ne, x, y)
1440
1441 for x, y in qnan_pairs + snan_pairs:
1442 for op in order_ops:
1443 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001444
Mark Dickinson84230a12010-02-18 14:49:50 +00001445 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001446 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001447
Stefan Krah1919b7e2012-03-21 18:25:23 +01001448 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001449 self.assertEqual(Decimal(1).copy_sign(-2), d)
1450 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1451
Stefan Krah1919b7e2012-03-21 18:25:23 +01001452class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1453 decimal = C
1454class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1455 decimal = P
1456
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001457# The following are two functions used to test threading in the next class
1458
1459def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001460 Decimal = cls.decimal.Decimal
1461 InvalidOperation = cls.decimal.InvalidOperation
1462 DivisionByZero = cls.decimal.DivisionByZero
1463 Overflow = cls.decimal.Overflow
1464 Underflow = cls.decimal.Underflow
1465 Inexact = cls.decimal.Inexact
1466 getcontext = cls.decimal.getcontext
1467 localcontext = cls.decimal.localcontext
1468
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001469 d1 = Decimal(1)
1470 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001471 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001472
Stefan Krah1919b7e2012-03-21 18:25:23 +01001473 cls.finish1.set()
1474 cls.synchro.wait()
1475
1476 test2 = d1/d3
1477 with localcontext() as c2:
1478 cls.assertTrue(c2.flags[Inexact])
1479 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1480 cls.assertTrue(c2.flags[DivisionByZero])
1481 with localcontext() as c3:
1482 cls.assertTrue(c3.flags[Inexact])
1483 cls.assertTrue(c3.flags[DivisionByZero])
1484 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1485 cls.assertTrue(c3.flags[InvalidOperation])
1486 del c3
1487 cls.assertFalse(c2.flags[InvalidOperation])
1488 del c2
1489
1490 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1491 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1492
1493 c1 = getcontext()
1494 cls.assertTrue(c1.flags[Inexact])
1495 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1496 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001497 return
1498
1499def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001500 Decimal = cls.decimal.Decimal
1501 InvalidOperation = cls.decimal.InvalidOperation
1502 DivisionByZero = cls.decimal.DivisionByZero
1503 Overflow = cls.decimal.Overflow
1504 Underflow = cls.decimal.Underflow
1505 Inexact = cls.decimal.Inexact
1506 getcontext = cls.decimal.getcontext
1507 localcontext = cls.decimal.localcontext
1508
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001509 d1 = Decimal(1)
1510 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001511 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001512
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001513 thiscontext = getcontext()
1514 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001515 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001516
1517 with localcontext() as c2:
1518 cls.assertTrue(c2.flags[Inexact])
1519 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1520 cls.assertTrue(c2.flags[Overflow])
1521 with localcontext(thiscontext) as c3:
1522 cls.assertTrue(c3.flags[Inexact])
1523 cls.assertFalse(c3.flags[Overflow])
1524 c3.traps[Underflow] = True
1525 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1526 cls.assertTrue(c3.flags[Underflow])
1527 del c3
1528 cls.assertFalse(c2.flags[Underflow])
1529 cls.assertFalse(c2.traps[Underflow])
1530 del c2
1531
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001532 cls.synchro.set()
1533 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001534
Stefan Krah1919b7e2012-03-21 18:25:23 +01001535 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001536 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001537
1538 cls.assertFalse(thiscontext.traps[Underflow])
1539 cls.assertTrue(thiscontext.flags[Inexact])
1540 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1541 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001542 return
1543
Stefan Krah1919b7e2012-03-21 18:25:23 +01001544class ThreadingTest(unittest.TestCase):
1545 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001546
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001547 # Take care executing this test from IDLE, there's an issue in threading
1548 # that hangs IDLE and I couldn't find it
1549
1550 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001551 DefaultContext = self.decimal.DefaultContext
1552
1553 if self.decimal == C and not self.decimal.HAVE_THREADS:
1554 self.skipTest("compiled without threading")
1555 # Test the "threading isolation" of a Context. Also test changing
1556 # the DefaultContext, which acts as a template for the thread-local
1557 # contexts.
1558 save_prec = DefaultContext.prec
1559 save_emax = DefaultContext.Emax
1560 save_emin = DefaultContext.Emin
1561 DefaultContext.prec = 24
1562 DefaultContext.Emax = 425000000
1563 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001564
1565 self.synchro = threading.Event()
1566 self.finish1 = threading.Event()
1567 self.finish2 = threading.Event()
1568
1569 th1 = threading.Thread(target=thfunc1, args=(self,))
1570 th2 = threading.Thread(target=thfunc2, args=(self,))
1571
1572 th1.start()
1573 th2.start()
1574
1575 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001576 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001577
1578 for sig in Signals[self.decimal]:
1579 self.assertFalse(DefaultContext.flags[sig])
1580
1581 DefaultContext.prec = save_prec
1582 DefaultContext.Emax = save_emax
1583 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001584 return
1585
Stefan Krah1919b7e2012-03-21 18:25:23 +01001586@unittest.skipUnless(threading, 'threading required')
1587class CThreadingTest(ThreadingTest):
1588 decimal = C
1589@unittest.skipUnless(threading, 'threading required')
1590class PyThreadingTest(ThreadingTest):
1591 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001592
Stefan Krah1919b7e2012-03-21 18:25:23 +01001593class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001594 '''Unit tests for Usability cases of Decimal.'''
1595
1596 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001597
Stefan Krah1919b7e2012-03-21 18:25:23 +01001598 Decimal = self.decimal.Decimal
1599
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001600 da = Decimal('23.42')
1601 db = Decimal('23.42')
1602 dc = Decimal('45')
1603
1604 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001605 self.assertGreater(dc, da)
1606 self.assertGreaterEqual(dc, da)
1607 self.assertLess(da, dc)
1608 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001609 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001610 self.assertNotEqual(da, dc)
1611 self.assertLessEqual(da, db)
1612 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001613
1614 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001615 self.assertGreater(dc, 23)
1616 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001617 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001618
1619 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001620 self.assertNotEqual(da, 'ugly')
1621 self.assertNotEqual(da, 32.7)
1622 self.assertNotEqual(da, object())
1623 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001624
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001625 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001626 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001627 b = a[:]
1628 random.shuffle(a)
1629 a.sort()
1630 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001631
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001632 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001633 Decimal = self.decimal.Decimal
1634
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001635 da = Decimal('0.25')
1636 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001637 self.assertLess(da, 3.0)
1638 self.assertLessEqual(da, 3.0)
1639 self.assertGreater(db, 0.25)
1640 self.assertGreaterEqual(db, 0.25)
1641 self.assertNotEqual(da, 1.5)
1642 self.assertEqual(da, 0.25)
1643 self.assertGreater(3.0, da)
1644 self.assertGreaterEqual(3.0, da)
1645 self.assertLess(0.25, db)
1646 self.assertLessEqual(0.25, db)
1647 self.assertNotEqual(0.25, db)
1648 self.assertEqual(3.0, db)
1649 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001650
Stefan Krah1919b7e2012-03-21 18:25:23 +01001651 def test_decimal_complex_comparison(self):
1652 Decimal = self.decimal.Decimal
1653
1654 da = Decimal('0.25')
1655 db = Decimal('3.0')
1656 self.assertNotEqual(da, (1.5+0j))
1657 self.assertNotEqual((1.5+0j), da)
1658 self.assertEqual(da, (0.25+0j))
1659 self.assertEqual((0.25+0j), da)
1660 self.assertEqual((3.0+0j), db)
1661 self.assertEqual(db, (3.0+0j))
1662
1663 self.assertNotEqual(db, (3.0+1j))
1664 self.assertNotEqual((3.0+1j), db)
1665
1666 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1667 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1668 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1669 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1670
1671 def test_decimal_fraction_comparison(self):
1672 D = self.decimal.Decimal
1673 F = fractions[self.decimal].Fraction
1674 Context = self.decimal.Context
1675 localcontext = self.decimal.localcontext
1676 InvalidOperation = self.decimal.InvalidOperation
1677
1678
1679 emax = C.MAX_EMAX if C else 999999999
1680 emin = C.MIN_EMIN if C else -999999999
1681 etiny = C.MIN_ETINY if C else -1999999997
1682 c = Context(Emax=emax, Emin=emin)
1683
1684 with localcontext(c):
1685 c.prec = emax
1686 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1687 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1688 self.assertLess(F(0,1), D("1e" + str(etiny)))
1689 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1690 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1691 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1692
1693 self.assertEqual(D("0.1"), F(1,10))
1694 self.assertEqual(F(1,10), D("0.1"))
1695
1696 c.prec = 300
1697 self.assertNotEqual(D(1)/3, F(1,3))
1698 self.assertNotEqual(F(1,3), D(1)/3)
1699
1700 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1701 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1702
1703 self.assertGreater(D('inf'), F(99999999999,123))
1704 self.assertGreater(D('inf'), F(-99999999999,123))
1705 self.assertLess(D('-inf'), F(99999999999,123))
1706 self.assertLess(D('-inf'), F(-99999999999,123))
1707
1708 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1709 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1710 self.assertNotEqual(D('nan'), F(-9,123))
1711 self.assertNotEqual(F(-9,123), D('nan'))
1712
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001713 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001714 Decimal = self.decimal.Decimal
1715
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001716 d = Decimal('43.24')
1717 c = copy.copy(d)
1718 self.assertEqual(id(c), id(d))
1719 dc = copy.deepcopy(d)
1720 self.assertEqual(id(dc), id(d))
1721
1722 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001723
1724 Decimal = self.decimal.Decimal
1725 localcontext = self.decimal.localcontext
1726
Stefan Krahdc817b22010-11-17 11:16:34 +00001727 def hashit(d):
1728 a = hash(d)
1729 b = d.__hash__()
1730 self.assertEqual(a, b)
1731 return a
1732
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001733 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001734 hashit(Decimal(23))
1735 hashit(Decimal('Infinity'))
1736 hashit(Decimal('-Infinity'))
1737 hashit(Decimal('nan123'))
1738 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001739
1740 test_values = [Decimal(sign*(2**m + n))
1741 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001742 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001743 for n in range(-10, 10)
1744 for sign in [-1, 1]]
1745 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001746 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001747 Decimal("-0"), # zeros
1748 Decimal("0.00"),
1749 Decimal("-0.000"),
1750 Decimal("0E10"),
1751 Decimal("-0E12"),
1752 Decimal("10.0"), # negative exponent
1753 Decimal("-23.00000"),
1754 Decimal("1230E100"), # positive exponent
1755 Decimal("-4.5678E50"),
1756 # a value for which hash(n) != hash(n % (2**64-1))
1757 # in Python pre-2.6
1758 Decimal(2**64 + 2**32 - 1),
1759 # selection of values which fail with the old (before
1760 # version 2.6) long.__hash__
1761 Decimal("1.634E100"),
1762 Decimal("90.697E100"),
1763 Decimal("188.83E100"),
1764 Decimal("1652.9E100"),
1765 Decimal("56531E100"),
1766 ])
1767
1768 # check that hash(d) == hash(int(d)) for integral values
1769 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001770 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001771
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001772 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001773 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001774 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001775 self.assertTrue(hashit(Decimal('Inf')))
1776 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001777
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001778 # check that the hashes of a Decimal float match when they
1779 # represent exactly the same values
1780 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1781 '34.0', '2.5', '112390.625', '-0.515625']
1782 for s in test_strings:
1783 f = float(s)
1784 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001785 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001786
Stefan Krah1919b7e2012-03-21 18:25:23 +01001787 with localcontext() as c:
1788 # check that the value of the hash doesn't depend on the
1789 # current context (issue #1757)
1790 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001791
Stefan Krah1919b7e2012-03-21 18:25:23 +01001792 c.prec = 6
1793 h1 = hashit(x)
1794 c.prec = 10
1795 h2 = hashit(x)
1796 c.prec = 16
1797 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001798
Stefan Krah1919b7e2012-03-21 18:25:23 +01001799 self.assertEqual(h1, h2)
1800 self.assertEqual(h1, h3)
1801
1802 c.prec = 10000
1803 x = 1100 ** 1248
1804 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001805
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001806 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001807 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001808
1809 d1 = Decimal('15.32')
1810 d2 = Decimal('28.5')
1811 l1 = 15
1812 l2 = 28
1813
1814 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001815 self.assertIs(min(d1,d2), d1)
1816 self.assertIs(min(d2,d1), d1)
1817 self.assertIs(max(d1,d2), d2)
1818 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001819
1820 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001821 self.assertIs(min(d1,l2), d1)
1822 self.assertIs(min(l2,d1), d1)
1823 self.assertIs(max(l1,d2), d2)
1824 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001825
1826 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001827 Decimal = self.decimal.Decimal
1828
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001829 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001830 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001831 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001832 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001833
1834 def test_tostring_methods(self):
1835 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001836 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001837
1838 d = Decimal('15.32')
1839 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001840 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001841
1842 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001843 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001844 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001845
1846 d1 = Decimal('66')
1847 d2 = Decimal('15.32')
1848
1849 #int
1850 self.assertEqual(int(d1), 66)
1851 self.assertEqual(int(d2), 15)
1852
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001853 #float
1854 self.assertEqual(float(d1), 66)
1855 self.assertEqual(float(d2), 15.32)
1856
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001857 #floor
1858 test_pairs = [
1859 ('123.00', 123),
1860 ('3.2', 3),
1861 ('3.54', 3),
1862 ('3.899', 3),
1863 ('-2.3', -3),
1864 ('-11.0', -11),
1865 ('0.0', 0),
1866 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001867 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001868 ]
1869 for d, i in test_pairs:
1870 self.assertEqual(math.floor(Decimal(d)), i)
1871 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1872 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1873 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1874 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1875 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1876
1877 #ceiling
1878 test_pairs = [
1879 ('123.00', 123),
1880 ('3.2', 4),
1881 ('3.54', 4),
1882 ('3.899', 4),
1883 ('-2.3', -2),
1884 ('-11.0', -11),
1885 ('0.0', 0),
1886 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001887 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001888 ]
1889 for d, i in test_pairs:
1890 self.assertEqual(math.ceil(Decimal(d)), i)
1891 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1892 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1893 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1894 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1895 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1896
1897 #round, single argument
1898 test_pairs = [
1899 ('123.00', 123),
1900 ('3.2', 3),
1901 ('3.54', 4),
1902 ('3.899', 4),
1903 ('-2.3', -2),
1904 ('-11.0', -11),
1905 ('0.0', 0),
1906 ('-0E3', 0),
1907 ('-3.5', -4),
1908 ('-2.5', -2),
1909 ('-1.5', -2),
1910 ('-0.5', 0),
1911 ('0.5', 0),
1912 ('1.5', 2),
1913 ('2.5', 2),
1914 ('3.5', 4),
1915 ]
1916 for d, i in test_pairs:
1917 self.assertEqual(round(Decimal(d)), i)
1918 self.assertRaises(ValueError, round, Decimal('-NaN'))
1919 self.assertRaises(ValueError, round, Decimal('sNaN'))
1920 self.assertRaises(ValueError, round, Decimal('NaN123'))
1921 self.assertRaises(OverflowError, round, Decimal('Inf'))
1922 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1923
1924 #round, two arguments; this is essentially equivalent
1925 #to quantize, which is already extensively tested
1926 test_triples = [
1927 ('123.456', -4, '0E+4'),
1928 ('123.456', -3, '0E+3'),
1929 ('123.456', -2, '1E+2'),
1930 ('123.456', -1, '1.2E+2'),
1931 ('123.456', 0, '123'),
1932 ('123.456', 1, '123.5'),
1933 ('123.456', 2, '123.46'),
1934 ('123.456', 3, '123.456'),
1935 ('123.456', 4, '123.4560'),
1936 ('123.455', 2, '123.46'),
1937 ('123.445', 2, '123.44'),
1938 ('Inf', 4, 'NaN'),
1939 ('-Inf', -23, 'NaN'),
1940 ('sNaN314', 3, 'NaN314'),
1941 ]
1942 for d, n, r in test_triples:
1943 self.assertEqual(str(round(Decimal(d), n)), r)
1944
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001945 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001946 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001947
1948 #with zero
1949 d = Decimal( (0, (0,), 0) )
1950 self.assertEqual(d, eval(repr(d)))
1951
1952 #int
1953 d = Decimal( (1, (4, 5), 0) )
1954 self.assertEqual(d, eval(repr(d)))
1955
1956 #float
1957 d = Decimal( (0, (4, 5, 3, 4), -2) )
1958 self.assertEqual(d, eval(repr(d)))
1959
1960 #weird
1961 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1962 self.assertEqual(d, eval(repr(d)))
1963
1964 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001965 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001966
1967 #with zero
1968 d = Decimal(0)
1969 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1970
1971 #int
1972 d = Decimal(-45)
1973 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1974
1975 #complicated string
1976 d = Decimal("-4.34913534E-17")
1977 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1978
Stefan Krah1919b7e2012-03-21 18:25:23 +01001979 # XXX non-compliant infinity payload.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001980 d = Decimal("Infinity")
1981 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1982
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001983 #leading zeros in coefficient should be stripped
1984 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1985 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1986 d = Decimal( (1, (0, 0, 0), 37) )
1987 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1988 d = Decimal( (1, (), 37) )
1989 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1990
1991 #leading zeros in NaN diagnostic info should be stripped
1992 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1993 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1994 d = Decimal( (1, (0, 0, 0), 'N') )
1995 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1996 d = Decimal( (1, (), 'n') )
1997 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1998
Stefan Krah1919b7e2012-03-21 18:25:23 +01001999 # XXX coefficient in infinity should raise an error
2000 if self.decimal == P:
2001 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2002 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2003 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2004 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002005
Stefan Krah1919b7e2012-03-21 18:25:23 +01002006 def test_subclassing(self):
2007 # Different behaviours when subclassing Decimal
2008 Decimal = self.decimal.Decimal
2009
2010 class MyDecimal(Decimal):
2011 pass
2012
2013 d1 = MyDecimal(1)
2014 d2 = MyDecimal(2)
2015 d = d1 + d2
2016 self.assertIs(type(d), Decimal)
2017
2018 d = d1.max(d2)
2019 self.assertIs(type(d), Decimal)
2020
2021 d = copy.copy(d1)
2022 self.assertIs(type(d), MyDecimal)
2023 self.assertEqual(d, d1)
2024
2025 d = copy.deepcopy(d1)
2026 self.assertIs(type(d), MyDecimal)
2027 self.assertEqual(d, d1)
2028
2029 def test_implicit_context(self):
2030 Decimal = self.decimal.Decimal
2031 getcontext = self.decimal.getcontext
2032
2033 # Check results when context given implicitly. (Issue 2478)
2034 c = getcontext()
2035 self.assertEqual(str(Decimal(0).sqrt()),
2036 str(c.sqrt(Decimal(0))))
2037
2038 def test_conversions_from_int(self):
2039 # Check that methods taking a second Decimal argument will
2040 # always accept an integer in place of a Decimal.
2041 Decimal = self.decimal.Decimal
2042
2043 self.assertEqual(Decimal(4).compare(3),
2044 Decimal(4).compare(Decimal(3)))
2045 self.assertEqual(Decimal(4).compare_signal(3),
2046 Decimal(4).compare_signal(Decimal(3)))
2047 self.assertEqual(Decimal(4).compare_total(3),
2048 Decimal(4).compare_total(Decimal(3)))
2049 self.assertEqual(Decimal(4).compare_total_mag(3),
2050 Decimal(4).compare_total_mag(Decimal(3)))
2051 self.assertEqual(Decimal(10101).logical_and(1001),
2052 Decimal(10101).logical_and(Decimal(1001)))
2053 self.assertEqual(Decimal(10101).logical_or(1001),
2054 Decimal(10101).logical_or(Decimal(1001)))
2055 self.assertEqual(Decimal(10101).logical_xor(1001),
2056 Decimal(10101).logical_xor(Decimal(1001)))
2057 self.assertEqual(Decimal(567).max(123),
2058 Decimal(567).max(Decimal(123)))
2059 self.assertEqual(Decimal(567).max_mag(123),
2060 Decimal(567).max_mag(Decimal(123)))
2061 self.assertEqual(Decimal(567).min(123),
2062 Decimal(567).min(Decimal(123)))
2063 self.assertEqual(Decimal(567).min_mag(123),
2064 Decimal(567).min_mag(Decimal(123)))
2065 self.assertEqual(Decimal(567).next_toward(123),
2066 Decimal(567).next_toward(Decimal(123)))
2067 self.assertEqual(Decimal(1234).quantize(100),
2068 Decimal(1234).quantize(Decimal(100)))
2069 self.assertEqual(Decimal(768).remainder_near(1234),
2070 Decimal(768).remainder_near(Decimal(1234)))
2071 self.assertEqual(Decimal(123).rotate(1),
2072 Decimal(123).rotate(Decimal(1)))
2073 self.assertEqual(Decimal(1234).same_quantum(1000),
2074 Decimal(1234).same_quantum(Decimal(1000)))
2075 self.assertEqual(Decimal('9.123').scaleb(-100),
2076 Decimal('9.123').scaleb(Decimal(-100)))
2077 self.assertEqual(Decimal(456).shift(-1),
2078 Decimal(456).shift(Decimal(-1)))
2079
2080 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2081 Decimal(-12).fma(Decimal(45), Decimal(67)))
2082 self.assertEqual(Decimal(-12).fma(45, 67),
2083 Decimal(-12).fma(Decimal(45), Decimal(67)))
2084 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2085 Decimal(-12).fma(Decimal(45), Decimal(67)))
2086
2087class CUsabilityTest(UsabilityTest):
2088 decimal = C
2089class PyUsabilityTest(UsabilityTest):
2090 decimal = P
2091
2092class PythonAPItests(unittest.TestCase):
2093
2094 def test_abc(self):
2095 Decimal = self.decimal.Decimal
2096
2097 self.assertTrue(issubclass(Decimal, numbers.Number))
2098 self.assertFalse(issubclass(Decimal, numbers.Real))
2099 self.assertIsInstance(Decimal(0), numbers.Number)
2100 self.assertNotIsInstance(Decimal(0), numbers.Real)
2101
2102 def test_pickle(self):
2103 Decimal = self.decimal.Decimal
2104
2105 savedecimal = sys.modules['decimal']
2106
2107 # Round trip
2108 sys.modules['decimal'] = self.decimal
2109 d = Decimal('-3.141590000')
2110 p = pickle.dumps(d)
2111 e = pickle.loads(p)
2112 self.assertEqual(d, e)
2113
2114 if C:
2115 # Test interchangeability
2116 x = C.Decimal('-3.123e81723')
2117 y = P.Decimal('-3.123e81723')
2118
2119 sys.modules['decimal'] = C
2120 sx = pickle.dumps(x)
2121 sys.modules['decimal'] = P
2122 r = pickle.loads(sx)
2123 self.assertIsInstance(r, P.Decimal)
2124 self.assertEqual(r, y)
2125
2126 sys.modules['decimal'] = P
2127 sy = pickle.dumps(y)
2128 sys.modules['decimal'] = C
2129 r = pickle.loads(sy)
2130 self.assertIsInstance(r, C.Decimal)
2131 self.assertEqual(r, x)
2132
2133 sys.modules['decimal'] = savedecimal
2134
2135 def test_int(self):
2136 Decimal = self.decimal.Decimal
2137 ROUND_DOWN = self.decimal.ROUND_DOWN
2138
2139 for x in range(-250, 250):
2140 s = '%0.2f' % (x / 100.0)
2141 # should work the same as for floats
2142 self.assertEqual(int(Decimal(s)), int(float(s)))
2143 # should work the same as to_integral in the ROUND_DOWN mode
2144 d = Decimal(s)
2145 r = d.to_integral(ROUND_DOWN)
2146 self.assertEqual(Decimal(int(d)), r)
2147
2148 self.assertRaises(ValueError, int, Decimal('-nan'))
2149 self.assertRaises(ValueError, int, Decimal('snan'))
2150 self.assertRaises(OverflowError, int, Decimal('inf'))
2151 self.assertRaises(OverflowError, int, Decimal('-inf'))
2152
2153 def test_trunc(self):
2154 Decimal = self.decimal.Decimal
2155 ROUND_DOWN = self.decimal.ROUND_DOWN
2156
2157 for x in range(-250, 250):
2158 s = '%0.2f' % (x / 100.0)
2159 # should work the same as for floats
2160 self.assertEqual(int(Decimal(s)), int(float(s)))
2161 # should work the same as to_integral in the ROUND_DOWN mode
2162 d = Decimal(s)
2163 r = d.to_integral(ROUND_DOWN)
2164 self.assertEqual(Decimal(math.trunc(d)), r)
2165
2166 def test_from_float(self):
2167
2168 Decimal = self.decimal.Decimal
2169
2170 class MyDecimal(Decimal):
2171 pass
2172
2173 self.assertTrue(issubclass(MyDecimal, Decimal))
2174
2175 r = MyDecimal.from_float(0.1)
2176 self.assertEqual(type(r), MyDecimal)
2177 self.assertEqual(str(r),
2178 '0.1000000000000000055511151231257827021181583404541015625')
2179 bigint = 12345678901234567890123456789
2180 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2181 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2182 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2183 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2184 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2185 str(Decimal('NaN')))
2186 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2187 str(Decimal('Infinity')))
2188 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2189 str(Decimal('-Infinity')))
2190 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2191 for i in range(200):
2192 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2193 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2194
2195 def test_create_decimal_from_float(self):
2196 Decimal = self.decimal.Decimal
2197 Context = self.decimal.Context
2198 ROUND_DOWN = self.decimal.ROUND_DOWN
2199 ROUND_UP = self.decimal.ROUND_UP
2200 Inexact = self.decimal.Inexact
2201
2202 context = Context(prec=5, rounding=ROUND_DOWN)
2203 self.assertEqual(
2204 context.create_decimal_from_float(math.pi),
2205 Decimal('3.1415')
2206 )
2207 context = Context(prec=5, rounding=ROUND_UP)
2208 self.assertEqual(
2209 context.create_decimal_from_float(math.pi),
2210 Decimal('3.1416')
2211 )
2212 context = Context(prec=5, traps=[Inexact])
2213 self.assertRaises(
2214 Inexact,
2215 context.create_decimal_from_float,
2216 math.pi
2217 )
2218 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2219 "Decimal('-0')")
2220 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2221 "Decimal('1')")
2222 self.assertEqual(repr(context.create_decimal_from_float(10)),
2223 "Decimal('10')")
2224
2225 def test_quantize(self):
2226 Decimal = self.decimal.Decimal
2227 Context = self.decimal.Context
2228 InvalidOperation = self.decimal.InvalidOperation
2229 ROUND_DOWN = self.decimal.ROUND_DOWN
2230
2231 c = Context(Emax=99999, Emin=-99999)
2232 self.assertEqual(
2233 Decimal('7.335').quantize(Decimal('.01')),
2234 Decimal('7.34')
2235 )
2236 self.assertEqual(
2237 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2238 Decimal('7.33')
2239 )
2240 self.assertRaises(
2241 InvalidOperation,
2242 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2243 )
2244
2245 c = Context()
2246 d = Decimal("0.871831e800")
2247 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2248 self.assertEqual(x, Decimal('8.71E+799'))
2249
2250 def test_complex(self):
2251 Decimal = self.decimal.Decimal
2252
2253 x = Decimal("9.8182731e181273")
2254 self.assertEqual(x.real, x)
2255 self.assertEqual(x.imag, 0)
2256 self.assertEqual(x.conjugate(), x)
2257
2258 x = Decimal("1")
2259 self.assertEqual(complex(x), complex(float(1)))
2260
2261 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2262 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2263 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2264 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2265
2266 def test_named_parameters(self):
2267 D = self.decimal.Decimal
2268 Context = self.decimal.Context
2269 localcontext = self.decimal.localcontext
2270 InvalidOperation = self.decimal.InvalidOperation
2271 Overflow = self.decimal.Overflow
2272
2273 xc = Context()
2274 xc.prec = 1
2275 xc.Emax = 1
2276 xc.Emin = -1
2277
2278 with localcontext() as c:
2279 c.clear_flags()
2280
2281 self.assertEqual(D(9, xc), 9)
2282 self.assertEqual(D(9, context=xc), 9)
2283 self.assertEqual(D(context=xc, value=9), 9)
2284 self.assertEqual(D(context=xc), 0)
2285 xc.clear_flags()
2286 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2287 self.assertTrue(xc.flags[InvalidOperation])
2288 self.assertFalse(c.flags[InvalidOperation])
2289
2290 xc.clear_flags()
2291 self.assertEqual(D(2).exp(context=xc), 7)
2292 self.assertRaises(Overflow, D(8).exp, context=xc)
2293 self.assertTrue(xc.flags[Overflow])
2294 self.assertFalse(c.flags[Overflow])
2295
2296 xc.clear_flags()
2297 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2298 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2299 self.assertTrue(xc.flags[InvalidOperation])
2300 self.assertFalse(c.flags[InvalidOperation])
2301
2302 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2303 self.assertEqual(D(-1).next_minus(context=xc), -2)
2304 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2305 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2306 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2307 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2308 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2309 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2310
2311 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2312 xc.clear_flags()
2313 self.assertRaises(InvalidOperation,
2314 D("0").compare_signal, D('nan'), context=xc)
2315 self.assertTrue(xc.flags[InvalidOperation])
2316 self.assertFalse(c.flags[InvalidOperation])
2317 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2318 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2319 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2320 D('-0.3'))
2321 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2322 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2323 D('0.0'))
2324 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2325 xc.clear_flags()
2326 self.assertRaises(InvalidOperation,
2327 D("0.2").quantize, D('1e10'), context=xc)
2328 self.assertTrue(xc.flags[InvalidOperation])
2329 self.assertFalse(c.flags[InvalidOperation])
2330 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2331 D('-0.5'))
2332
2333 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2334 D('7E+1'))
2335
2336 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2337 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2338 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2339 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2340 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2341 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2342 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2343 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2344
2345 self.assertFalse(D("0.01").is_normal(context=xc))
2346 self.assertTrue(D("0.01").is_subnormal(context=xc))
2347
2348 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2349 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2350 self.assertRaises(TypeError, D(1).radix, context=xc)
2351
2352 self.assertEqual(D(-111).logb(context=xc), 2)
2353 self.assertEqual(D(0).logical_invert(context=xc), 1)
2354 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2355 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2356
2357 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2358 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2359 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2360 self.assertEqual(D('23').rotate(1, context=xc), 3)
2361 self.assertEqual(D('23').rotate(1, context=xc), 3)
2362 xc.clear_flags()
2363 self.assertRaises(Overflow,
2364 D('23').scaleb, 1, context=xc)
2365 self.assertTrue(xc.flags[Overflow])
2366 self.assertFalse(c.flags[Overflow])
2367 self.assertEqual(D('23').shift(-1, context=xc), 0)
2368
2369 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2370 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2371
2372 if (self.decimal == C):
2373 self.assertRaises(TypeError, D(1).canonical, context=xc)
2374 self.assertEqual(D("-1").copy_abs(context=xc), 1)
2375 self.assertEqual(D("1").copy_negate(context=xc), -1)
2376 else:
2377 self.assertEqual(D(1).canonical(context=xc), 1)
2378 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2379 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2380
2381class CPythonAPItests(PythonAPItests):
2382 decimal = C
2383class PyPythonAPItests(PythonAPItests):
2384 decimal = P
2385
2386class ContextAPItests(unittest.TestCase):
2387
2388 def test_pickle(self):
2389
2390 Context = self.decimal.Context
2391
2392 savedecimal = sys.modules['decimal']
2393
2394 # Round trip
2395 sys.modules['decimal'] = self.decimal
2396 c = Context()
2397 e = pickle.loads(pickle.dumps(c))
2398
2399 self.assertEqual(c.prec, e.prec)
2400 self.assertEqual(c.Emin, e.Emin)
2401 self.assertEqual(c.Emax, e.Emax)
2402 self.assertEqual(c.rounding, e.rounding)
2403 self.assertEqual(c.capitals, e.capitals)
2404 self.assertEqual(c.clamp, e.clamp)
2405 self.assertEqual(c.flags, e.flags)
2406 self.assertEqual(c.traps, e.traps)
2407
2408 # Test interchangeability
2409 combinations = [(C, P), (P, C)] if C else [(P, P)]
2410 for dumper, loader in combinations:
2411 for ri, _ in enumerate(RoundingModes[dumper]):
2412 for fi, _ in enumerate(OrderedSignals[dumper]):
2413 for ti, _ in enumerate(OrderedSignals[dumper]):
2414
2415 prec = random.randrange(1, 100)
2416 emin = random.randrange(-100, 0)
2417 emax = random.randrange(1, 100)
2418 caps = random.randrange(2)
2419 clamp = random.randrange(2)
2420
2421 # One module dumps
2422 sys.modules['decimal'] = dumper
2423 c = dumper.Context(
2424 prec=prec, Emin=emin, Emax=emax,
2425 rounding=RoundingModes[dumper][ri],
2426 capitals=caps, clamp=clamp,
2427 flags=OrderedSignals[dumper][:fi],
2428 traps=OrderedSignals[dumper][:ti]
2429 )
2430 s = pickle.dumps(c)
2431
2432 # The other module loads
2433 sys.modules['decimal'] = loader
2434 d = pickle.loads(s)
2435 self.assertIsInstance(d, loader.Context)
2436
2437 self.assertEqual(d.prec, prec)
2438 self.assertEqual(d.Emin, emin)
2439 self.assertEqual(d.Emax, emax)
2440 self.assertEqual(d.rounding, RoundingModes[loader][ri])
2441 self.assertEqual(d.capitals, caps)
2442 self.assertEqual(d.clamp, clamp)
2443 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2444 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2445
2446 sys.modules['decimal'] = savedecimal
2447
2448 def test_equality_with_other_types(self):
2449 Decimal = self.decimal.Decimal
2450
2451 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2452 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2453
2454 def test_copy(self):
2455 # All copies should be deep
2456 Decimal = self.decimal.Decimal
2457 Context = self.decimal.Context
2458
2459 c = Context()
2460 d = c.copy()
2461 self.assertNotEqual(id(c), id(d))
2462 self.assertNotEqual(id(c.flags), id(d.flags))
2463 self.assertNotEqual(id(c.traps), id(d.traps))
2464 k1 = set(c.flags.keys())
2465 k2 = set(d.flags.keys())
2466 self.assertEqual(k1, k2)
2467 self.assertEqual(c.flags, d.flags)
2468
2469 def test__clamp(self):
2470 # In Python 3.2, the private attribute `_clamp` was made
2471 # public (issue 8540), with the old `_clamp` becoming a
2472 # property wrapping `clamp`. For the duration of Python 3.2
2473 # only, the attribute should be gettable/settable via both
2474 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2475 # removed.
2476 Context = self.decimal.Context
2477 c = Context()
2478 self.assertRaises(AttributeError, getattr, c, '_clamp')
2479
2480 def test_abs(self):
2481 Decimal = self.decimal.Decimal
2482 Context = self.decimal.Context
2483
2484 c = Context()
2485 d = c.abs(Decimal(-1))
2486 self.assertEqual(c.abs(-1), d)
2487 self.assertRaises(TypeError, c.abs, '-1')
2488
2489 def test_add(self):
2490 Decimal = self.decimal.Decimal
2491 Context = self.decimal.Context
2492
2493 c = Context()
2494 d = c.add(Decimal(1), Decimal(1))
2495 self.assertEqual(c.add(1, 1), d)
2496 self.assertEqual(c.add(Decimal(1), 1), d)
2497 self.assertEqual(c.add(1, Decimal(1)), d)
2498 self.assertRaises(TypeError, c.add, '1', 1)
2499 self.assertRaises(TypeError, c.add, 1, '1')
2500
2501 def test_compare(self):
2502 Decimal = self.decimal.Decimal
2503 Context = self.decimal.Context
2504
2505 c = Context()
2506 d = c.compare(Decimal(1), Decimal(1))
2507 self.assertEqual(c.compare(1, 1), d)
2508 self.assertEqual(c.compare(Decimal(1), 1), d)
2509 self.assertEqual(c.compare(1, Decimal(1)), d)
2510 self.assertRaises(TypeError, c.compare, '1', 1)
2511 self.assertRaises(TypeError, c.compare, 1, '1')
2512
2513 def test_compare_signal(self):
2514 Decimal = self.decimal.Decimal
2515 Context = self.decimal.Context
2516
2517 c = Context()
2518 d = c.compare_signal(Decimal(1), Decimal(1))
2519 self.assertEqual(c.compare_signal(1, 1), d)
2520 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2521 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2522 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2523 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2524
2525 def test_compare_total(self):
2526 Decimal = self.decimal.Decimal
2527 Context = self.decimal.Context
2528
2529 c = Context()
2530 d = c.compare_total(Decimal(1), Decimal(1))
2531 self.assertEqual(c.compare_total(1, 1), d)
2532 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2533 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2534 self.assertRaises(TypeError, c.compare_total, '1', 1)
2535 self.assertRaises(TypeError, c.compare_total, 1, '1')
2536
2537 def test_compare_total_mag(self):
2538 Decimal = self.decimal.Decimal
2539 Context = self.decimal.Context
2540
2541 c = Context()
2542 d = c.compare_total_mag(Decimal(1), Decimal(1))
2543 self.assertEqual(c.compare_total_mag(1, 1), d)
2544 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2545 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2546 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2547 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2548
2549 def test_copy_abs(self):
2550 Decimal = self.decimal.Decimal
2551 Context = self.decimal.Context
2552
2553 c = Context()
2554 d = c.copy_abs(Decimal(-1))
2555 self.assertEqual(c.copy_abs(-1), d)
2556 self.assertRaises(TypeError, c.copy_abs, '-1')
2557
2558 def test_copy_decimal(self):
2559 Decimal = self.decimal.Decimal
2560 Context = self.decimal.Context
2561
2562 c = Context()
2563 d = c.copy_decimal(Decimal(-1))
2564 self.assertEqual(c.copy_decimal(-1), d)
2565 self.assertRaises(TypeError, c.copy_decimal, '-1')
2566
2567 def test_copy_negate(self):
2568 Decimal = self.decimal.Decimal
2569 Context = self.decimal.Context
2570
2571 c = Context()
2572 d = c.copy_negate(Decimal(-1))
2573 self.assertEqual(c.copy_negate(-1), d)
2574 self.assertRaises(TypeError, c.copy_negate, '-1')
2575
2576 def test_copy_sign(self):
2577 Decimal = self.decimal.Decimal
2578 Context = self.decimal.Context
2579
2580 c = Context()
2581 d = c.copy_sign(Decimal(1), Decimal(-2))
2582 self.assertEqual(c.copy_sign(1, -2), d)
2583 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2584 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2585 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2586 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2587
2588 def test_divide(self):
2589 Decimal = self.decimal.Decimal
2590 Context = self.decimal.Context
2591
2592 c = Context()
2593 d = c.divide(Decimal(1), Decimal(2))
2594 self.assertEqual(c.divide(1, 2), d)
2595 self.assertEqual(c.divide(Decimal(1), 2), d)
2596 self.assertEqual(c.divide(1, Decimal(2)), d)
2597 self.assertRaises(TypeError, c.divide, '1', 2)
2598 self.assertRaises(TypeError, c.divide, 1, '2')
2599
2600 def test_divide_int(self):
2601 Decimal = self.decimal.Decimal
2602 Context = self.decimal.Context
2603
2604 c = Context()
2605 d = c.divide_int(Decimal(1), Decimal(2))
2606 self.assertEqual(c.divide_int(1, 2), d)
2607 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2608 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2609 self.assertRaises(TypeError, c.divide_int, '1', 2)
2610 self.assertRaises(TypeError, c.divide_int, 1, '2')
2611
2612 def test_divmod(self):
2613 Decimal = self.decimal.Decimal
2614 Context = self.decimal.Context
2615
2616 c = Context()
2617 d = c.divmod(Decimal(1), Decimal(2))
2618 self.assertEqual(c.divmod(1, 2), d)
2619 self.assertEqual(c.divmod(Decimal(1), 2), d)
2620 self.assertEqual(c.divmod(1, Decimal(2)), d)
2621 self.assertRaises(TypeError, c.divmod, '1', 2)
2622 self.assertRaises(TypeError, c.divmod, 1, '2')
2623
2624 def test_exp(self):
2625 Decimal = self.decimal.Decimal
2626 Context = self.decimal.Context
2627
2628 c = Context()
2629 d = c.exp(Decimal(10))
2630 self.assertEqual(c.exp(10), d)
2631 self.assertRaises(TypeError, c.exp, '10')
2632
2633 def test_fma(self):
2634 Decimal = self.decimal.Decimal
2635 Context = self.decimal.Context
2636
2637 c = Context()
2638 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
2639 self.assertEqual(c.fma(2, 3, 4), d)
2640 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
2641 self.assertEqual(c.fma(2, Decimal(3), 4), d)
2642 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
2643 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
2644 self.assertRaises(TypeError, c.fma, '2', 3, 4)
2645 self.assertRaises(TypeError, c.fma, 2, '3', 4)
2646 self.assertRaises(TypeError, c.fma, 2, 3, '4')
2647
2648 # Issue 12079 for Context.fma ...
2649 self.assertRaises(TypeError, c.fma,
2650 Decimal('Infinity'), Decimal(0), "not a decimal")
2651 self.assertRaises(TypeError, c.fma,
2652 Decimal(1), Decimal('snan'), 1.222)
2653 # ... and for Decimal.fma.
2654 self.assertRaises(TypeError, Decimal('Infinity').fma,
2655 Decimal(0), "not a decimal")
2656 self.assertRaises(TypeError, Decimal(1).fma,
2657 Decimal('snan'), 1.222)
2658
2659 def test_is_finite(self):
2660 Decimal = self.decimal.Decimal
2661 Context = self.decimal.Context
2662
2663 c = Context()
2664 d = c.is_finite(Decimal(10))
2665 self.assertEqual(c.is_finite(10), d)
2666 self.assertRaises(TypeError, c.is_finite, '10')
2667
2668 def test_is_infinite(self):
2669 Decimal = self.decimal.Decimal
2670 Context = self.decimal.Context
2671
2672 c = Context()
2673 d = c.is_infinite(Decimal(10))
2674 self.assertEqual(c.is_infinite(10), d)
2675 self.assertRaises(TypeError, c.is_infinite, '10')
2676
2677 def test_is_nan(self):
2678 Decimal = self.decimal.Decimal
2679 Context = self.decimal.Context
2680
2681 c = Context()
2682 d = c.is_nan(Decimal(10))
2683 self.assertEqual(c.is_nan(10), d)
2684 self.assertRaises(TypeError, c.is_nan, '10')
2685
2686 def test_is_normal(self):
2687 Decimal = self.decimal.Decimal
2688 Context = self.decimal.Context
2689
2690 c = Context()
2691 d = c.is_normal(Decimal(10))
2692 self.assertEqual(c.is_normal(10), d)
2693 self.assertRaises(TypeError, c.is_normal, '10')
2694
2695 def test_is_qnan(self):
2696 Decimal = self.decimal.Decimal
2697 Context = self.decimal.Context
2698
2699 c = Context()
2700 d = c.is_qnan(Decimal(10))
2701 self.assertEqual(c.is_qnan(10), d)
2702 self.assertRaises(TypeError, c.is_qnan, '10')
2703
2704 def test_is_signed(self):
2705 Decimal = self.decimal.Decimal
2706 Context = self.decimal.Context
2707
2708 c = Context()
2709 d = c.is_signed(Decimal(10))
2710 self.assertEqual(c.is_signed(10), d)
2711 self.assertRaises(TypeError, c.is_signed, '10')
2712
2713 def test_is_snan(self):
2714 Decimal = self.decimal.Decimal
2715 Context = self.decimal.Context
2716
2717 c = Context()
2718 d = c.is_snan(Decimal(10))
2719 self.assertEqual(c.is_snan(10), d)
2720 self.assertRaises(TypeError, c.is_snan, '10')
2721
2722 def test_is_subnormal(self):
2723 Decimal = self.decimal.Decimal
2724 Context = self.decimal.Context
2725
2726 c = Context()
2727 d = c.is_subnormal(Decimal(10))
2728 self.assertEqual(c.is_subnormal(10), d)
2729 self.assertRaises(TypeError, c.is_subnormal, '10')
2730
2731 def test_is_zero(self):
2732 Decimal = self.decimal.Decimal
2733 Context = self.decimal.Context
2734
2735 c = Context()
2736 d = c.is_zero(Decimal(10))
2737 self.assertEqual(c.is_zero(10), d)
2738 self.assertRaises(TypeError, c.is_zero, '10')
2739
2740 def test_ln(self):
2741 Decimal = self.decimal.Decimal
2742 Context = self.decimal.Context
2743
2744 c = Context()
2745 d = c.ln(Decimal(10))
2746 self.assertEqual(c.ln(10), d)
2747 self.assertRaises(TypeError, c.ln, '10')
2748
2749 def test_log10(self):
2750 Decimal = self.decimal.Decimal
2751 Context = self.decimal.Context
2752
2753 c = Context()
2754 d = c.log10(Decimal(10))
2755 self.assertEqual(c.log10(10), d)
2756 self.assertRaises(TypeError, c.log10, '10')
2757
2758 def test_logb(self):
2759 Decimal = self.decimal.Decimal
2760 Context = self.decimal.Context
2761
2762 c = Context()
2763 d = c.logb(Decimal(10))
2764 self.assertEqual(c.logb(10), d)
2765 self.assertRaises(TypeError, c.logb, '10')
2766
2767 def test_logical_and(self):
2768 Decimal = self.decimal.Decimal
2769 Context = self.decimal.Context
2770
2771 c = Context()
2772 d = c.logical_and(Decimal(1), Decimal(1))
2773 self.assertEqual(c.logical_and(1, 1), d)
2774 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2775 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2776 self.assertRaises(TypeError, c.logical_and, '1', 1)
2777 self.assertRaises(TypeError, c.logical_and, 1, '1')
2778
2779 def test_logical_invert(self):
2780 Decimal = self.decimal.Decimal
2781 Context = self.decimal.Context
2782
2783 c = Context()
2784 d = c.logical_invert(Decimal(1000))
2785 self.assertEqual(c.logical_invert(1000), d)
2786 self.assertRaises(TypeError, c.logical_invert, '1000')
2787
2788 def test_logical_or(self):
2789 Decimal = self.decimal.Decimal
2790 Context = self.decimal.Context
2791
2792 c = Context()
2793 d = c.logical_or(Decimal(1), Decimal(1))
2794 self.assertEqual(c.logical_or(1, 1), d)
2795 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2796 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2797 self.assertRaises(TypeError, c.logical_or, '1', 1)
2798 self.assertRaises(TypeError, c.logical_or, 1, '1')
2799
2800 def test_logical_xor(self):
2801 Decimal = self.decimal.Decimal
2802 Context = self.decimal.Context
2803
2804 c = Context()
2805 d = c.logical_xor(Decimal(1), Decimal(1))
2806 self.assertEqual(c.logical_xor(1, 1), d)
2807 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2808 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2809 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2810 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2811
2812 def test_max(self):
2813 Decimal = self.decimal.Decimal
2814 Context = self.decimal.Context
2815
2816 c = Context()
2817 d = c.max(Decimal(1), Decimal(2))
2818 self.assertEqual(c.max(1, 2), d)
2819 self.assertEqual(c.max(Decimal(1), 2), d)
2820 self.assertEqual(c.max(1, Decimal(2)), d)
2821 self.assertRaises(TypeError, c.max, '1', 2)
2822 self.assertRaises(TypeError, c.max, 1, '2')
2823
2824 def test_max_mag(self):
2825 Decimal = self.decimal.Decimal
2826 Context = self.decimal.Context
2827
2828 c = Context()
2829 d = c.max_mag(Decimal(1), Decimal(2))
2830 self.assertEqual(c.max_mag(1, 2), d)
2831 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2832 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2833 self.assertRaises(TypeError, c.max_mag, '1', 2)
2834 self.assertRaises(TypeError, c.max_mag, 1, '2')
2835
2836 def test_min(self):
2837 Decimal = self.decimal.Decimal
2838 Context = self.decimal.Context
2839
2840 c = Context()
2841 d = c.min(Decimal(1), Decimal(2))
2842 self.assertEqual(c.min(1, 2), d)
2843 self.assertEqual(c.min(Decimal(1), 2), d)
2844 self.assertEqual(c.min(1, Decimal(2)), d)
2845 self.assertRaises(TypeError, c.min, '1', 2)
2846 self.assertRaises(TypeError, c.min, 1, '2')
2847
2848 def test_min_mag(self):
2849 Decimal = self.decimal.Decimal
2850 Context = self.decimal.Context
2851
2852 c = Context()
2853 d = c.min_mag(Decimal(1), Decimal(2))
2854 self.assertEqual(c.min_mag(1, 2), d)
2855 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2856 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2857 self.assertRaises(TypeError, c.min_mag, '1', 2)
2858 self.assertRaises(TypeError, c.min_mag, 1, '2')
2859
2860 def test_minus(self):
2861 Decimal = self.decimal.Decimal
2862 Context = self.decimal.Context
2863
2864 c = Context()
2865 d = c.minus(Decimal(10))
2866 self.assertEqual(c.minus(10), d)
2867 self.assertRaises(TypeError, c.minus, '10')
2868
2869 def test_multiply(self):
2870 Decimal = self.decimal.Decimal
2871 Context = self.decimal.Context
2872
2873 c = Context()
2874 d = c.multiply(Decimal(1), Decimal(2))
2875 self.assertEqual(c.multiply(1, 2), d)
2876 self.assertEqual(c.multiply(Decimal(1), 2), d)
2877 self.assertEqual(c.multiply(1, Decimal(2)), d)
2878 self.assertRaises(TypeError, c.multiply, '1', 2)
2879 self.assertRaises(TypeError, c.multiply, 1, '2')
2880
2881 def test_next_minus(self):
2882 Decimal = self.decimal.Decimal
2883 Context = self.decimal.Context
2884
2885 c = Context()
2886 d = c.next_minus(Decimal(10))
2887 self.assertEqual(c.next_minus(10), d)
2888 self.assertRaises(TypeError, c.next_minus, '10')
2889
2890 def test_next_plus(self):
2891 Decimal = self.decimal.Decimal
2892 Context = self.decimal.Context
2893
2894 c = Context()
2895 d = c.next_plus(Decimal(10))
2896 self.assertEqual(c.next_plus(10), d)
2897 self.assertRaises(TypeError, c.next_plus, '10')
2898
2899 def test_next_toward(self):
2900 Decimal = self.decimal.Decimal
2901 Context = self.decimal.Context
2902
2903 c = Context()
2904 d = c.next_toward(Decimal(1), Decimal(2))
2905 self.assertEqual(c.next_toward(1, 2), d)
2906 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2907 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2908 self.assertRaises(TypeError, c.next_toward, '1', 2)
2909 self.assertRaises(TypeError, c.next_toward, 1, '2')
2910
2911 def test_normalize(self):
2912 Decimal = self.decimal.Decimal
2913 Context = self.decimal.Context
2914
2915 c = Context()
2916 d = c.normalize(Decimal(10))
2917 self.assertEqual(c.normalize(10), d)
2918 self.assertRaises(TypeError, c.normalize, '10')
2919
2920 def test_number_class(self):
2921 Decimal = self.decimal.Decimal
2922 Context = self.decimal.Context
2923
2924 c = Context()
2925 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2926 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2927 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2928
2929 def test_plus(self):
2930 Decimal = self.decimal.Decimal
2931 Context = self.decimal.Context
2932
2933 c = Context()
2934 d = c.plus(Decimal(10))
2935 self.assertEqual(c.plus(10), d)
2936 self.assertRaises(TypeError, c.plus, '10')
2937
2938 def test_power(self):
2939 Decimal = self.decimal.Decimal
2940 Context = self.decimal.Context
2941
2942 c = Context()
2943 d = c.power(Decimal(1), Decimal(4))
2944 self.assertEqual(c.power(1, 4), d)
2945 self.assertEqual(c.power(Decimal(1), 4), d)
2946 self.assertEqual(c.power(1, Decimal(4)), d)
2947 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
2948 self.assertRaises(TypeError, c.power, '1', 4)
2949 self.assertRaises(TypeError, c.power, 1, '4')
2950 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
2951
2952 def test_quantize(self):
2953 Decimal = self.decimal.Decimal
2954 Context = self.decimal.Context
2955
2956 c = Context()
2957 d = c.quantize(Decimal(1), Decimal(2))
2958 self.assertEqual(c.quantize(1, 2), d)
2959 self.assertEqual(c.quantize(Decimal(1), 2), d)
2960 self.assertEqual(c.quantize(1, Decimal(2)), d)
2961 self.assertRaises(TypeError, c.quantize, '1', 2)
2962 self.assertRaises(TypeError, c.quantize, 1, '2')
2963
2964 def test_remainder(self):
2965 Decimal = self.decimal.Decimal
2966 Context = self.decimal.Context
2967
2968 c = Context()
2969 d = c.remainder(Decimal(1), Decimal(2))
2970 self.assertEqual(c.remainder(1, 2), d)
2971 self.assertEqual(c.remainder(Decimal(1), 2), d)
2972 self.assertEqual(c.remainder(1, Decimal(2)), d)
2973 self.assertRaises(TypeError, c.remainder, '1', 2)
2974 self.assertRaises(TypeError, c.remainder, 1, '2')
2975
2976 def test_remainder_near(self):
2977 Decimal = self.decimal.Decimal
2978 Context = self.decimal.Context
2979
2980 c = Context()
2981 d = c.remainder_near(Decimal(1), Decimal(2))
2982 self.assertEqual(c.remainder_near(1, 2), d)
2983 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2984 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2985 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2986 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2987
2988 def test_rotate(self):
2989 Decimal = self.decimal.Decimal
2990 Context = self.decimal.Context
2991
2992 c = Context()
2993 d = c.rotate(Decimal(1), Decimal(2))
2994 self.assertEqual(c.rotate(1, 2), d)
2995 self.assertEqual(c.rotate(Decimal(1), 2), d)
2996 self.assertEqual(c.rotate(1, Decimal(2)), d)
2997 self.assertRaises(TypeError, c.rotate, '1', 2)
2998 self.assertRaises(TypeError, c.rotate, 1, '2')
2999
3000 def test_sqrt(self):
3001 Decimal = self.decimal.Decimal
3002 Context = self.decimal.Context
3003
3004 c = Context()
3005 d = c.sqrt(Decimal(10))
3006 self.assertEqual(c.sqrt(10), d)
3007 self.assertRaises(TypeError, c.sqrt, '10')
3008
3009 def test_same_quantum(self):
3010 Decimal = self.decimal.Decimal
3011 Context = self.decimal.Context
3012
3013 c = Context()
3014 d = c.same_quantum(Decimal(1), Decimal(2))
3015 self.assertEqual(c.same_quantum(1, 2), d)
3016 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3017 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3018 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3019 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3020
3021 def test_scaleb(self):
3022 Decimal = self.decimal.Decimal
3023 Context = self.decimal.Context
3024
3025 c = Context()
3026 d = c.scaleb(Decimal(1), Decimal(2))
3027 self.assertEqual(c.scaleb(1, 2), d)
3028 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3029 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3030 self.assertRaises(TypeError, c.scaleb, '1', 2)
3031 self.assertRaises(TypeError, c.scaleb, 1, '2')
3032
3033 def test_shift(self):
3034 Decimal = self.decimal.Decimal
3035 Context = self.decimal.Context
3036
3037 c = Context()
3038 d = c.shift(Decimal(1), Decimal(2))
3039 self.assertEqual(c.shift(1, 2), d)
3040 self.assertEqual(c.shift(Decimal(1), 2), d)
3041 self.assertEqual(c.shift(1, Decimal(2)), d)
3042 self.assertRaises(TypeError, c.shift, '1', 2)
3043 self.assertRaises(TypeError, c.shift, 1, '2')
3044
3045 def test_subtract(self):
3046 Decimal = self.decimal.Decimal
3047 Context = self.decimal.Context
3048
3049 c = Context()
3050 d = c.subtract(Decimal(1), Decimal(2))
3051 self.assertEqual(c.subtract(1, 2), d)
3052 self.assertEqual(c.subtract(Decimal(1), 2), d)
3053 self.assertEqual(c.subtract(1, Decimal(2)), d)
3054 self.assertRaises(TypeError, c.subtract, '1', 2)
3055 self.assertRaises(TypeError, c.subtract, 1, '2')
3056
3057 def test_to_eng_string(self):
3058 Decimal = self.decimal.Decimal
3059 Context = self.decimal.Context
3060
3061 c = Context()
3062 d = c.to_eng_string(Decimal(10))
3063 self.assertEqual(c.to_eng_string(10), d)
3064 self.assertRaises(TypeError, c.to_eng_string, '10')
3065
3066 def test_to_sci_string(self):
3067 Decimal = self.decimal.Decimal
3068 Context = self.decimal.Context
3069
3070 c = Context()
3071 d = c.to_sci_string(Decimal(10))
3072 self.assertEqual(c.to_sci_string(10), d)
3073 self.assertRaises(TypeError, c.to_sci_string, '10')
3074
3075 def test_to_integral_exact(self):
3076 Decimal = self.decimal.Decimal
3077 Context = self.decimal.Context
3078
3079 c = Context()
3080 d = c.to_integral_exact(Decimal(10))
3081 self.assertEqual(c.to_integral_exact(10), d)
3082 self.assertRaises(TypeError, c.to_integral_exact, '10')
3083
3084 def test_to_integral_value(self):
3085 Decimal = self.decimal.Decimal
3086 Context = self.decimal.Context
3087
3088 c = Context()
3089 d = c.to_integral_value(Decimal(10))
3090 self.assertEqual(c.to_integral_value(10), d)
3091 self.assertRaises(TypeError, c.to_integral_value, '10')
3092 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3093
3094class CContextAPItests(ContextAPItests):
3095 decimal = C
3096class PyContextAPItests(ContextAPItests):
3097 decimal = P
3098
3099class ContextWithStatement(unittest.TestCase):
3100 # Can't do these as docstrings until Python 2.6
3101 # as doctest can't handle __future__ statements
3102
3103 def test_localcontext(self):
3104 # Use a copy of the current context in the block
3105 getcontext = self.decimal.getcontext
3106 localcontext = self.decimal.localcontext
3107
3108 orig_ctx = getcontext()
3109 with localcontext() as enter_ctx:
3110 set_ctx = getcontext()
3111 final_ctx = getcontext()
3112 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3113 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3114 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3115
3116 def test_localcontextarg(self):
3117 # Use a copy of the supplied context in the block
3118 Context = self.decimal.Context
3119 getcontext = self.decimal.getcontext
3120 localcontext = self.decimal.localcontext
3121
3122 localcontext = self.decimal.localcontext
3123 orig_ctx = getcontext()
3124 new_ctx = Context(prec=42)
3125 with localcontext(new_ctx) as enter_ctx:
3126 set_ctx = getcontext()
3127 final_ctx = getcontext()
3128 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3129 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3130 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3131 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3132
3133 def test_nested_with_statements(self):
3134 # Use a copy of the supplied context in the block
3135 Decimal = self.decimal.Decimal
3136 Context = self.decimal.Context
3137 getcontext = self.decimal.getcontext
3138 localcontext = self.decimal.localcontext
3139 Clamped = self.decimal.Clamped
3140 Overflow = self.decimal.Overflow
3141
3142 orig_ctx = getcontext()
3143 orig_ctx.clear_flags()
3144 new_ctx = Context(Emax=384)
3145 with localcontext() as c1:
3146 self.assertEqual(c1.flags, orig_ctx.flags)
3147 self.assertEqual(c1.traps, orig_ctx.traps)
3148 c1.traps[Clamped] = True
3149 c1.Emin = -383
3150 self.assertNotEqual(orig_ctx.Emin, -383)
3151 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3152 self.assertTrue(c1.flags[Clamped])
3153 with localcontext(new_ctx) as c2:
3154 self.assertEqual(c2.flags, new_ctx.flags)
3155 self.assertEqual(c2.traps, new_ctx.traps)
3156 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3157 self.assertFalse(c2.flags[Clamped])
3158 self.assertTrue(c2.flags[Overflow])
3159 del c2
3160 self.assertFalse(c1.flags[Overflow])
3161 del c1
3162 self.assertNotEqual(orig_ctx.Emin, -383)
3163 self.assertFalse(orig_ctx.flags[Clamped])
3164 self.assertFalse(orig_ctx.flags[Overflow])
3165 self.assertFalse(new_ctx.flags[Clamped])
3166 self.assertFalse(new_ctx.flags[Overflow])
3167
3168 def test_with_statements_gc1(self):
3169 localcontext = self.decimal.localcontext
3170
3171 with localcontext() as c1:
3172 del c1
3173 with localcontext() as c2:
3174 del c2
3175 with localcontext() as c3:
3176 del c3
3177 with localcontext() as c4:
3178 del c4
3179
3180 def test_with_statements_gc2(self):
3181 localcontext = self.decimal.localcontext
3182
3183 with localcontext() as c1:
3184 with localcontext(c1) as c2:
3185 del c1
3186 with localcontext(c2) as c3:
3187 del c2
3188 with localcontext(c3) as c4:
3189 del c3
3190 del c4
3191
3192 def test_with_statements_gc3(self):
3193 Context = self.decimal.Context
3194 localcontext = self.decimal.localcontext
3195 getcontext = self.decimal.getcontext
3196 setcontext = self.decimal.setcontext
3197
3198 with localcontext() as c1:
3199 del c1
3200 n1 = Context(prec=1)
3201 setcontext(n1)
3202 with localcontext(n1) as c2:
3203 del n1
3204 self.assertEqual(c2.prec, 1)
3205 del c2
3206 n2 = Context(prec=2)
3207 setcontext(n2)
3208 del n2
3209 self.assertEqual(getcontext().prec, 2)
3210 n3 = Context(prec=3)
3211 setcontext(n3)
3212 self.assertEqual(getcontext().prec, 3)
3213 with localcontext(n3) as c3:
3214 del n3
3215 self.assertEqual(c3.prec, 3)
3216 del c3
3217 n4 = Context(prec=4)
3218 setcontext(n4)
3219 del n4
3220 self.assertEqual(getcontext().prec, 4)
3221 with localcontext() as c4:
3222 self.assertEqual(c4.prec, 4)
3223 del c4
3224
3225class CContextWithStatement(ContextWithStatement):
3226 decimal = C
3227class PyContextWithStatement(ContextWithStatement):
3228 decimal = P
3229
3230class ContextFlags(unittest.TestCase):
3231
3232 def test_flags_irrelevant(self):
3233 # check that the result (numeric result + flags raised) of an
3234 # arithmetic operation doesn't depend on the current flags
3235 Decimal = self.decimal.Decimal
3236 Context = self.decimal.Context
3237 Inexact = self.decimal.Inexact
3238 Rounded = self.decimal.Rounded
3239 Underflow = self.decimal.Underflow
3240 Clamped = self.decimal.Clamped
3241 Subnormal = self.decimal.Subnormal
3242 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
3243
3244 def raise_error(context, flag):
3245 if self.decimal == C:
3246 context.flags[flag] = True
3247 if context.traps[flag]:
3248 raise flag
3249 else:
3250 context._raise_error(flag)
3251
3252 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3253 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3254
3255 # operations that raise various flags, in the form (function, arglist)
3256 operations = [
3257 (context._apply, [Decimal("100E-425000010")]),
3258 (context.sqrt, [Decimal(2)]),
3259 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3260 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3261 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3262 ]
3263
3264 # try various flags individually, then a whole lot at once
3265 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3266 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3267
3268 for fn, args in operations:
3269 # find answer and flags raised using a clean context
3270 context.clear_flags()
3271 ans = fn(*args)
3272 flags = [k for k, v in context.flags.items() if v]
3273
3274 for extra_flags in flagsets:
3275 # set flags, before calling operation
3276 context.clear_flags()
3277 for flag in extra_flags:
3278 raise_error(context, flag)
3279 new_ans = fn(*args)
3280
3281 # flags that we expect to be set after the operation
3282 expected_flags = list(flags)
3283 for flag in extra_flags:
3284 if flag not in expected_flags:
3285 expected_flags.append(flag)
3286 expected_flags.sort(key=id)
3287
3288 # flags we actually got
3289 new_flags = [k for k,v in context.flags.items() if v]
3290 new_flags.sort(key=id)
3291
3292 self.assertEqual(ans, new_ans,
3293 "operation produces different answers depending on flags set: " +
3294 "expected %s, got %s." % (ans, new_ans))
3295 self.assertEqual(new_flags, expected_flags,
3296 "operation raises different flags depending on flags set: " +
3297 "expected %s, got %s" % (expected_flags, new_flags))
3298
3299 def test_flag_comparisons(self):
3300 Context = self.decimal.Context
3301 Inexact = self.decimal.Inexact
3302 Rounded = self.decimal.Rounded
3303
3304 c = Context()
3305
3306 # Valid SignalDict
3307 self.assertNotEqual(c.flags, c.traps)
3308 self.assertNotEqual(c.traps, c.flags)
3309
3310 c.flags = c.traps
3311 self.assertEqual(c.flags, c.traps)
3312 self.assertEqual(c.traps, c.flags)
3313
3314 c.flags[Rounded] = True
3315 c.traps = c.flags
3316 self.assertEqual(c.flags, c.traps)
3317 self.assertEqual(c.traps, c.flags)
3318
3319 d = {}
3320 d.update(c.flags)
3321 self.assertEqual(d, c.flags)
3322 self.assertEqual(c.flags, d)
3323
3324 d[Inexact] = True
3325 self.assertNotEqual(d, c.flags)
3326 self.assertNotEqual(c.flags, d)
3327
3328 # Invalid SignalDict
3329 d = {Inexact:False}
3330 self.assertNotEqual(d, c.flags)
3331 self.assertNotEqual(c.flags, d)
3332
3333 d = ["xyz"]
3334 self.assertNotEqual(d, c.flags)
3335 self.assertNotEqual(c.flags, d)
3336
3337 @requires_IEEE_754
3338 def test_float_operation(self):
3339 Decimal = self.decimal.Decimal
3340 FloatOperation = self.decimal.FloatOperation
3341 localcontext = self.decimal.localcontext
3342
3343 with localcontext() as c:
3344 ##### trap is off by default
3345 self.assertFalse(c.traps[FloatOperation])
3346
3347 # implicit conversion sets the flag
3348 c.clear_flags()
3349 self.assertEqual(Decimal(7.5), 7.5)
3350 self.assertTrue(c.flags[FloatOperation])
3351
3352 c.clear_flags()
3353 self.assertEqual(c.create_decimal(7.5), 7.5)
3354 self.assertTrue(c.flags[FloatOperation])
3355
3356 # explicit conversion does not set the flag
3357 c.clear_flags()
3358 x = Decimal.from_float(7.5)
3359 self.assertFalse(c.flags[FloatOperation])
3360 # comparison sets the flag
3361 self.assertEqual(x, 7.5)
3362 self.assertTrue(c.flags[FloatOperation])
3363
3364 c.clear_flags()
3365 x = c.create_decimal_from_float(7.5)
3366 self.assertFalse(c.flags[FloatOperation])
3367 self.assertEqual(x, 7.5)
3368 self.assertTrue(c.flags[FloatOperation])
3369
3370 ##### set the trap
3371 c.traps[FloatOperation] = True
3372
3373 # implicit conversion raises
3374 c.clear_flags()
3375 self.assertRaises(FloatOperation, Decimal, 7.5)
3376 self.assertTrue(c.flags[FloatOperation])
3377
3378 c.clear_flags()
3379 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3380 self.assertTrue(c.flags[FloatOperation])
3381
3382 # explicit conversion is silent
3383 c.clear_flags()
3384 x = Decimal.from_float(7.5)
3385 self.assertFalse(c.flags[FloatOperation])
3386
3387 c.clear_flags()
3388 x = c.create_decimal_from_float(7.5)
3389 self.assertFalse(c.flags[FloatOperation])
3390
3391 def test_float_comparison(self):
3392 Decimal = self.decimal.Decimal
3393 Context = self.decimal.Context
3394 FloatOperation = self.decimal.FloatOperation
3395 localcontext = self.decimal.localcontext
3396
3397 def assert_attr(a, b, attr, context, signal=None):
3398 context.clear_flags()
3399 f = getattr(a, attr)
3400 if signal == FloatOperation:
3401 self.assertRaises(signal, f, b)
3402 else:
3403 self.assertIs(f(b), True)
3404 self.assertTrue(context.flags[FloatOperation])
3405
3406 small_d = Decimal('0.25')
3407 big_d = Decimal('3.0')
3408 small_f = 0.25
3409 big_f = 3.0
3410
3411 zero_d = Decimal('0.0')
3412 neg_zero_d = Decimal('-0.0')
3413 zero_f = 0.0
3414 neg_zero_f = -0.0
3415
3416 inf_d = Decimal('Infinity')
3417 neg_inf_d = Decimal('-Infinity')
3418 inf_f = float('inf')
3419 neg_inf_f = float('-inf')
3420
3421 def doit(c, signal=None):
3422 # Order
3423 for attr in '__lt__', '__le__':
3424 assert_attr(small_d, big_f, attr, c, signal)
3425
3426 for attr in '__gt__', '__ge__':
3427 assert_attr(big_d, small_f, attr, c, signal)
3428
3429 # Equality
3430 assert_attr(small_d, small_f, '__eq__', c, None)
3431
3432 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3433 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3434
3435 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3436 assert_attr(zero_d, zero_f, '__eq__', c, None)
3437
3438 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3439 assert_attr(inf_d, inf_f, '__eq__', c, None)
3440
3441 # Inequality
3442 assert_attr(small_d, big_f, '__ne__', c, None)
3443
3444 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3445
3446 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3447 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3448
3449 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3450
3451 def test_containers(c, signal=None):
3452 c.clear_flags()
3453 s = set([100.0, Decimal('100.0')])
3454 self.assertEqual(len(s), 1)
3455 self.assertTrue(c.flags[FloatOperation])
3456
3457 c.clear_flags()
3458 if signal:
3459 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3460 else:
3461 s = sorted([10.0, Decimal('10.0')])
3462 self.assertTrue(c.flags[FloatOperation])
3463
3464 c.clear_flags()
3465 b = 10.0 in [Decimal('10.0'), 1.0]
3466 self.assertTrue(c.flags[FloatOperation])
3467
3468 c.clear_flags()
3469 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3470 self.assertTrue(c.flags[FloatOperation])
3471
3472 nc = Context()
3473 with localcontext(nc) as c:
3474 self.assertFalse(c.traps[FloatOperation])
3475 doit(c, signal=None)
3476 test_containers(c, signal=None)
3477
3478 c.traps[FloatOperation] = True
3479 doit(c, signal=FloatOperation)
3480 test_containers(c, signal=FloatOperation)
3481
3482 def test_float_operation_default(self):
3483 Decimal = self.decimal.Decimal
3484 Context = self.decimal.Context
3485 Inexact = self.decimal.Inexact
3486 FloatOperation= self.decimal.FloatOperation
3487
3488 context = Context()
3489 self.assertFalse(context.flags[FloatOperation])
3490 self.assertFalse(context.traps[FloatOperation])
3491
3492 context.clear_traps()
3493 context.traps[Inexact] = True
3494 context.traps[FloatOperation] = True
3495 self.assertTrue(context.traps[FloatOperation])
3496 self.assertTrue(context.traps[Inexact])
3497
3498class CContextFlags(ContextFlags):
3499 decimal = C
3500class PyContextFlags(ContextFlags):
3501 decimal = P
3502
3503class SpecialContexts(unittest.TestCase):
3504 """Test the context templates."""
3505
3506 def test_context_templates(self):
3507 BasicContext = self.decimal.BasicContext
3508 ExtendedContext = self.decimal.ExtendedContext
3509 getcontext = self.decimal.getcontext
3510 setcontext = self.decimal.setcontext
3511 InvalidOperation = self.decimal.InvalidOperation
3512 DivisionByZero = self.decimal.DivisionByZero
3513 Overflow = self.decimal.Overflow
3514 Underflow = self.decimal.Underflow
3515 Clamped = self.decimal.Clamped
3516
3517 assert_signals(self, BasicContext, 'traps',
3518 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3519 )
3520
3521 savecontext = getcontext().copy()
3522 basic_context_prec = BasicContext.prec
3523 extended_context_prec = ExtendedContext.prec
3524
3525 ex = None
3526 try:
3527 BasicContext.prec = ExtendedContext.prec = 441
3528 for template in BasicContext, ExtendedContext:
3529 setcontext(template)
3530 c = getcontext()
3531 self.assertIsNot(c, template)
3532 self.assertEqual(c.prec, 441)
3533 except Exception as e:
3534 ex = e.__class__
3535 finally:
3536 BasicContext.prec = basic_context_prec
3537 ExtendedContext.prec = extended_context_prec
3538 setcontext(savecontext)
3539 if ex:
3540 raise ex
3541
3542 def test_default_context(self):
3543 DefaultContext = self.decimal.DefaultContext
3544 BasicContext = self.decimal.BasicContext
3545 ExtendedContext = self.decimal.ExtendedContext
3546 getcontext = self.decimal.getcontext
3547 setcontext = self.decimal.setcontext
3548 InvalidOperation = self.decimal.InvalidOperation
3549 DivisionByZero = self.decimal.DivisionByZero
3550 Overflow = self.decimal.Overflow
3551
3552 self.assertEqual(BasicContext.prec, 9)
3553 self.assertEqual(ExtendedContext.prec, 9)
3554
3555 assert_signals(self, DefaultContext, 'traps',
3556 [InvalidOperation, DivisionByZero, Overflow]
3557 )
3558
3559 savecontext = getcontext().copy()
3560 default_context_prec = DefaultContext.prec
3561
3562 ex = None
3563 try:
3564 c = getcontext()
3565 saveprec = c.prec
3566
3567 DefaultContext.prec = 961
3568 c = getcontext()
3569 self.assertEqual(c.prec, saveprec)
3570
3571 setcontext(DefaultContext)
3572 c = getcontext()
3573 self.assertIsNot(c, DefaultContext)
3574 self.assertEqual(c.prec, 961)
3575 except Exception as e:
3576 ex = e.__class__
3577 finally:
3578 DefaultContext.prec = default_context_prec
3579 setcontext(savecontext)
3580 if ex:
3581 raise ex
3582
3583class CSpecialContexts(SpecialContexts):
3584 decimal = C
3585class PySpecialContexts(SpecialContexts):
3586 decimal = P
3587
3588class ContextInputValidation(unittest.TestCase):
3589
3590 def test_invalid_context(self):
3591 Context = self.decimal.Context
3592 DefaultContext = self.decimal.DefaultContext
3593
3594 c = DefaultContext.copy()
3595
3596 # prec, Emax
3597 for attr in ['prec', 'Emax']:
3598 setattr(c, attr, 999999)
3599 self.assertEqual(getattr(c, attr), 999999)
3600 self.assertRaises(ValueError, setattr, c, attr, -1)
3601 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3602
3603 # Emin
3604 setattr(c, 'Emin', -999999)
3605 self.assertEqual(getattr(c, 'Emin'), -999999)
3606 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3607 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3608
3609 # rounding: always raise TypeError in order to get consistent
3610 # exceptions across implementations. In decimal, rounding
3611 # modes are strings, in _decimal they are integers. The idea
3612 # is to view rounding as an abstract type and not mind the
3613 # implementation details.
3614 # Hence, a user should view the rounding modes as if they
3615 # had been defined in a language that supports abstract
3616 # data types, e.g. ocaml:
3617 #
3618 # type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;;
3619 #
3620 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3621 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3622 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3623 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3624
3625 # capitals, clamp
3626 for attr in ['capitals', 'clamp']:
3627 self.assertRaises(ValueError, setattr, c, attr, -1)
3628 self.assertRaises(ValueError, setattr, c, attr, 2)
3629 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3630
3631 # Invalid attribute
3632 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3633
3634 # Invalid signal dict
3635 self.assertRaises(TypeError, setattr, c, 'flags', [])
3636 self.assertRaises(KeyError, setattr, c, 'flags', {})
3637 self.assertRaises(KeyError, setattr, c, 'traps',
3638 {'InvalidOperation':0})
3639
3640 # Attributes cannot be deleted
3641 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3642 'flags', 'traps']:
3643 self.assertRaises(AttributeError, c.__delattr__, attr)
3644
3645 # Invalid attributes
3646 self.assertRaises(TypeError, getattr, c, 9)
3647 self.assertRaises(TypeError, setattr, c, 9)
3648
3649 # Invalid values in constructor
3650 self.assertRaises(TypeError, Context, rounding=999999)
3651 self.assertRaises(TypeError, Context, rounding='xyz')
3652 self.assertRaises(ValueError, Context, clamp=2)
3653 self.assertRaises(ValueError, Context, capitals=-1)
3654 self.assertRaises(KeyError, Context, flags=["P"])
3655 self.assertRaises(KeyError, Context, traps=["Q"])
3656
3657 # Type error in conversion
3658 self.assertRaises(TypeError, Context, flags=(0,1))
3659 self.assertRaises(TypeError, Context, traps=(1,0))
3660
3661class CContextInputValidation(ContextInputValidation):
3662 decimal = C
3663class PyContextInputValidation(ContextInputValidation):
3664 decimal = P
3665
3666class ContextSubclassing(unittest.TestCase):
3667
3668 def test_context_subclassing(self):
3669 decimal = self.decimal
3670 Decimal = decimal.Decimal
3671 Context = decimal.Context
3672 ROUND_HALF_EVEN = decimal.ROUND_HALF_EVEN
3673 ROUND_DOWN = decimal.ROUND_DOWN
3674 Clamped = decimal.Clamped
3675 DivisionByZero = decimal.DivisionByZero
3676 Inexact = decimal.Inexact
3677 Overflow = decimal.Overflow
3678 Rounded = decimal.Rounded
3679 Subnormal = decimal.Subnormal
3680 Underflow = decimal.Underflow
3681 InvalidOperation = decimal.InvalidOperation
3682
3683 class MyContext(Context):
3684 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
3685 capitals=None, clamp=None, flags=None,
3686 traps=None):
3687 Context.__init__(self)
3688 if prec is not None:
3689 self.prec = prec
3690 if rounding is not None:
3691 self.rounding = rounding
3692 if Emin is not None:
3693 self.Emin = Emin
3694 if Emax is not None:
3695 self.Emax = Emax
3696 if capitals is not None:
3697 self.capitals = capitals
3698 if clamp is not None:
3699 self.clamp = clamp
3700 if flags is not None:
3701 if isinstance(flags, list):
3702 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
3703 self.flags = flags
3704 if traps is not None:
3705 if isinstance(traps, list):
3706 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
3707 self.traps = traps
3708
3709 c = Context()
3710 d = MyContext()
3711 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
3712 'flags', 'traps'):
3713 self.assertEqual(getattr(c, attr), getattr(d, attr))
3714
3715 # prec
3716 self.assertRaises(ValueError, MyContext, **{'prec':-1})
3717 c = MyContext(prec=1)
3718 self.assertEqual(c.prec, 1)
3719 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
3720
3721 # rounding
3722 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
3723 c = MyContext(rounding=ROUND_DOWN, prec=1)
3724 self.assertEqual(c.rounding, ROUND_DOWN)
3725 self.assertEqual(c.plus(Decimal('9.9')), 9)
3726
3727 # Emin
3728 self.assertRaises(ValueError, MyContext, **{'Emin':5})
3729 c = MyContext(Emin=-1, prec=1)
3730 self.assertEqual(c.Emin, -1)
3731 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
3732 self.assertEqual(x, Decimal('0.0'))
3733 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
3734 self.assertTrue(c.flags[signal])
3735
3736 # Emax
3737 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
3738 c = MyContext(Emax=1, prec=1)
3739 self.assertEqual(c.Emax, 1)
3740 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
3741 if self.decimal == C:
3742 for signal in (Inexact, Overflow, Rounded):
3743 self.assertTrue(c.flags[signal])
3744
3745 # capitals
3746 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
3747 c = MyContext(capitals=0)
3748 self.assertEqual(c.capitals, 0)
3749 x = c.create_decimal('1E222')
3750 self.assertEqual(c.to_sci_string(x), '1e+222')
3751
3752 # clamp
3753 self.assertRaises(ValueError, MyContext, **{'clamp':2})
3754 c = MyContext(clamp=1, Emax=99)
3755 self.assertEqual(c.clamp, 1)
3756 x = c.plus(Decimal('1e99'))
3757 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
3758
3759 # flags
3760 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
3761 c = MyContext(flags=[Rounded, DivisionByZero])
3762 for signal in (Rounded, DivisionByZero):
3763 self.assertTrue(c.flags[signal])
3764 c.clear_flags()
3765 for signal in OrderedSignals[decimal]:
3766 self.assertFalse(c.flags[signal])
3767
3768 # traps
3769 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
3770 c = MyContext(traps=[Rounded, DivisionByZero])
3771 for signal in (Rounded, DivisionByZero):
3772 self.assertTrue(c.traps[signal])
3773 c.clear_traps()
3774 for signal in OrderedSignals[decimal]:
3775 self.assertFalse(c.traps[signal])
3776
3777class CContextSubclassing(ContextSubclassing):
3778 decimal = C
3779class PyContextSubclassing(ContextSubclassing):
3780 decimal = P
3781
3782@skip_if_extra_functionality
3783class CheckAttributes(unittest.TestCase):
3784
3785 def test_module_attributes(self):
3786
3787 # Architecture dependent context limits
3788 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
3789 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
3790 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
3791 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
3792
3793 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
3794 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
3795
3796 self.assertEqual(C.__version__, P.__version__)
3797
3798 x = dir(C)
3799 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
3800 self.assertEqual(set(x) - set(y), {'MallocError'})
3801
3802 def test_context_attributes(self):
3803
3804 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
3805 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
3806 self.assertEqual(set(x) - set(y), set())
3807
3808 def test_decimal_attributes(self):
3809
3810 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3811 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3812 self.assertEqual(set(x) - set(y), set())
3813
3814class Coverage(unittest.TestCase):
3815
3816 def test_adjusted(self):
3817 Decimal = self.decimal.Decimal
3818
3819 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
3820 # XXX raise?
3821 self.assertEqual(Decimal('nan').adjusted(), 0)
3822 self.assertEqual(Decimal('inf').adjusted(), 0)
3823
3824 def test_canonical(self):
3825 Decimal = self.decimal.Decimal
3826 getcontext = self.decimal.getcontext
3827
3828 x = Decimal(9).canonical()
3829 self.assertEqual(x, 9)
3830
3831 c = getcontext()
3832 x = c.canonical(Decimal(9))
3833 self.assertEqual(x, 9)
3834
3835 def test_context_repr(self):
3836 c = self.decimal.DefaultContext.copy()
3837
3838 c.prec = 425000000
3839 c.Emax = 425000000
3840 c.Emin = -425000000
3841 c.rounding = self.decimal.ROUND_HALF_DOWN
3842 c.capitals = 0
3843 c.clamp = 1
3844 for sig in OrderedSignals[self.decimal]:
3845 c.flags[sig] = False
3846 c.traps[sig] = False
3847
3848 s = c.__repr__()
3849 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
3850 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
3851 "flags=[], traps=[])"
3852 self.assertEqual(s, t)
3853
3854 def test_implicit_context(self):
3855 Decimal = self.decimal.Decimal
3856 localcontext = self.decimal.localcontext
3857
3858 with localcontext() as c:
3859 c.prec = 1
3860 c.Emax = 1
3861 c.Emin = -1
3862
3863 # abs
3864 self.assertEqual(abs(Decimal("-10")), 10)
3865 # add
3866 self.assertEqual(Decimal("7") + 1, 8)
3867 # divide
3868 self.assertEqual(Decimal("10") / 5, 2)
3869 # divide_int
3870 self.assertEqual(Decimal("10") // 7, 1)
3871 # fma
3872 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
3873 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
3874 # three arg power
3875 self.assertEqual(pow(Decimal(10), 2, 7), 2)
3876 # exp
3877 self.assertEqual(Decimal("1.01").exp(), 3)
3878 # is_normal
3879 self.assertIs(Decimal("0.01").is_normal(), False)
3880 # is_subnormal
3881 self.assertIs(Decimal("0.01").is_subnormal(), True)
3882 # ln
3883 self.assertEqual(Decimal("20").ln(), 3)
3884 # log10
3885 self.assertEqual(Decimal("20").log10(), 1)
3886 # logb
3887 self.assertEqual(Decimal("580").logb(), 2)
3888 # logical_invert
3889 self.assertEqual(Decimal("10").logical_invert(), 1)
3890 # minus
3891 self.assertEqual(-Decimal("-10"), 10)
3892 # multiply
3893 self.assertEqual(Decimal("2") * 4, 8)
3894 # next_minus
3895 self.assertEqual(Decimal("10").next_minus(), 9)
3896 # next_plus
3897 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
3898 # normalize
3899 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
3900 # number_class
3901 self.assertEqual(Decimal("10").number_class(), '+Normal')
3902 # plus
3903 self.assertEqual(+Decimal("-1"), -1)
3904 # remainder
3905 self.assertEqual(Decimal("10") % 7, 3)
3906 # subtract
3907 self.assertEqual(Decimal("10") - 7, 3)
3908 # to_integral_exact
3909 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
3910
3911 # Boolean functions
3912 self.assertTrue(Decimal("1").is_canonical())
3913 self.assertTrue(Decimal("1").is_finite())
3914 self.assertTrue(Decimal("1").is_finite())
3915 self.assertTrue(Decimal("snan").is_snan())
3916 self.assertTrue(Decimal("-1").is_signed())
3917 self.assertTrue(Decimal("0").is_zero())
3918 self.assertTrue(Decimal("0").is_zero())
3919
3920 # Copy
3921 with localcontext() as c:
3922 c.prec = 10000
3923 x = 1228 ** 1523
3924 y = -Decimal(x)
3925
3926 z = y.copy_abs()
3927 self.assertEqual(z, x)
3928
3929 z = y.copy_negate()
3930 self.assertEqual(z, x)
3931
3932 z = y.copy_sign(Decimal(1))
3933 self.assertEqual(z, x)
3934
3935 def test_divmod(self):
3936 Decimal = self.decimal.Decimal
3937 localcontext = self.decimal.localcontext
3938 InvalidOperation = self.decimal.InvalidOperation
3939 DivisionByZero = self.decimal.DivisionByZero
3940
3941 with localcontext() as c:
3942 q, r = divmod(Decimal("10912837129"), 1001)
3943 self.assertEqual(q, Decimal('10901935'))
3944 self.assertEqual(r, Decimal('194'))
3945
3946 q, r = divmod(Decimal("NaN"), 7)
3947 self.assertTrue(q.is_nan() and r.is_nan())
3948
3949 c.traps[InvalidOperation] = False
3950 q, r = divmod(Decimal("NaN"), 7)
3951 self.assertTrue(q.is_nan() and r.is_nan())
3952
3953 c.traps[InvalidOperation] = False
3954 c.clear_flags()
3955 q, r = divmod(Decimal("inf"), Decimal("inf"))
3956 self.assertTrue(q.is_nan() and r.is_nan())
3957 self.assertTrue(c.flags[InvalidOperation])
3958
3959 c.clear_flags()
3960 q, r = divmod(Decimal("inf"), 101)
3961 self.assertTrue(q.is_infinite() and r.is_nan())
3962 self.assertTrue(c.flags[InvalidOperation])
3963
3964 c.clear_flags()
3965 q, r = divmod(Decimal(0), 0)
3966 self.assertTrue(q.is_nan() and r.is_nan())
3967 self.assertTrue(c.flags[InvalidOperation])
3968
3969 c.traps[DivisionByZero] = False
3970 c.clear_flags()
3971 q, r = divmod(Decimal(11), 0)
3972 self.assertTrue(q.is_infinite() and r.is_nan())
3973 self.assertTrue(c.flags[InvalidOperation] and
3974 c.flags[DivisionByZero])
3975
3976 def test_power(self):
3977 Decimal = self.decimal.Decimal
3978 localcontext = self.decimal.localcontext
3979 Overflow = self.decimal.Overflow
3980 Rounded = self.decimal.Rounded
3981
3982 with localcontext() as c:
3983 c.prec = 3
3984 c.clear_flags()
3985 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
3986 self.assertTrue(c.flags[Rounded])
3987
3988 c.prec = 1
3989 c.Emax = 1
3990 c.Emin = -1
3991 c.clear_flags()
3992 c.traps[Overflow] = False
3993 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
3994 self.assertTrue(c.flags[Overflow])
3995
3996 def test_quantize(self):
3997 Decimal = self.decimal.Decimal
3998 localcontext = self.decimal.localcontext
3999 InvalidOperation = self.decimal.InvalidOperation
4000
4001 with localcontext() as c:
4002 c.prec = 1
4003 c.Emax = 1
4004 c.Emin = -1
4005 c.traps[InvalidOperation] = False
4006 x = Decimal(99).quantize(Decimal("1e1"))
4007 self.assertTrue(x.is_nan())
4008
4009 def test_radix(self):
4010 Decimal = self.decimal.Decimal
4011 getcontext = self.decimal.getcontext
4012
4013 c = getcontext()
4014 self.assertEqual(Decimal("1").radix(), 10)
4015 self.assertEqual(c.radix(), 10)
4016
4017 def test_rop(self):
4018 Decimal = self.decimal.Decimal
4019
4020 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4021 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4022 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4023
4024 def test_round(self):
4025 # Python3 behavior: round() returns Decimal
4026 Decimal = self.decimal.Decimal
4027 getcontext = self.decimal.getcontext
4028
4029 c = getcontext()
4030 c.prec = 28
4031
4032 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4033 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4034 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4035 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4036 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4037
4038 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4039 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4040
4041 def test_create_decimal(self):
4042 c = self.decimal.Context()
4043 self.assertRaises(ValueError, c.create_decimal, ["%"])
4044
4045 def test_int(self):
4046 Decimal = self.decimal.Decimal
4047 localcontext = self.decimal.localcontext
4048
4049 with localcontext() as c:
4050 c.prec = 9999
4051 x = Decimal(1221**1271) / 10**3923
4052 self.assertEqual(int(x), 1)
4053 self.assertEqual(x.to_integral(), 2)
4054
4055 def test_copy(self):
4056 Context = self.decimal.Context
4057
4058 c = Context()
4059 c.prec = 10000
4060 x = -(1172 ** 1712)
4061
4062 y = c.copy_abs(x)
4063 self.assertEqual(y, -x)
4064
4065 y = c.copy_negate(x)
4066 self.assertEqual(y, -x)
4067
4068 y = c.copy_sign(x, 1)
4069 self.assertEqual(y, -x)
4070
4071class CCoverage(Coverage):
4072 decimal = C
4073class PyCoverage(Coverage):
4074 decimal = P
4075
4076class PyFunctionality(unittest.TestCase):
4077 """Extra functionality in decimal.py"""
4078
4079 def test_py_quantize_watchexp(self):
4080 # watchexp functionality
4081 Decimal = P.Decimal
4082 localcontext = P.localcontext
4083
4084 with localcontext() as c:
4085 c.prec = 1
4086 c.Emax = 1
4087 c.Emin = -1
4088 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4089 self.assertEqual(x, Decimal('1.00E+5'))
4090
4091 def test_py_alternate_formatting(self):
4092 # triples giving a format, a Decimal, and the expected result
4093 Decimal = P.Decimal
4094 localcontext = P.localcontext
4095
4096 test_values = [
4097 # Issue 7094: Alternate formatting (specified by #)
4098 ('.0e', '1.0', '1e+0'),
4099 ('#.0e', '1.0', '1.e+0'),
4100 ('.0f', '1.0', '1'),
4101 ('#.0f', '1.0', '1.'),
4102 ('g', '1.1', '1.1'),
4103 ('#g', '1.1', '1.1'),
4104 ('.0g', '1', '1'),
4105 ('#.0g', '1', '1.'),
4106 ('.0%', '1.0', '100%'),
4107 ('#.0%', '1.0', '100.%'),
4108 ]
4109 for fmt, d, result in test_values:
4110 self.assertEqual(format(Decimal(d), fmt), result)
4111
4112class PyWhitebox(unittest.TestCase):
4113 """White box testing for decimal.py"""
4114
4115 def test_py_exact_power(self):
4116 # Rarely exercised lines in _power_exact.
4117 Decimal = P.Decimal
4118 localcontext = P.localcontext
4119
4120 with localcontext() as c:
4121 c.prec = 8
4122 x = Decimal(2**16) ** Decimal("-0.5")
4123 self.assertEqual(x, Decimal('0.00390625'))
4124
4125 x = Decimal(2**16) ** Decimal("-0.6")
4126 self.assertEqual(x, Decimal('0.0012885819'))
4127
4128 x = Decimal("256e7") ** Decimal("-0.5")
4129
4130 x = Decimal(152587890625) ** Decimal('-0.0625')
4131 self.assertEqual(x, Decimal("0.2"))
4132
4133 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4134
4135 x = Decimal(5**2659) ** Decimal('-0.0625')
4136
4137 c.prec = 1
4138 x = Decimal("152587890625") ** Decimal('-0.5')
4139 c.prec = 201
4140 x = Decimal(2**578) ** Decimal("-0.5")
4141
4142 def test_py_immutability_operations(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004143 # Do operations and check that it didn't change change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004144 Decimal = P.Decimal
4145 DefaultContext = P.DefaultContext
4146 setcontext = P.setcontext
4147
4148 c = DefaultContext.copy()
4149 c.traps = dict((s, 0) for s in OrderedSignals[P])
4150 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004151
4152 d1 = Decimal('-25e55')
4153 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004154 d2 = Decimal('33e+33')
4155 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004156
4157 def checkSameDec(operation, useOther=False):
4158 if useOther:
4159 eval("d1." + operation + "(d2)")
4160 self.assertEqual(d1._sign, b1._sign)
4161 self.assertEqual(d1._int, b1._int)
4162 self.assertEqual(d1._exp, b1._exp)
4163 self.assertEqual(d2._sign, b2._sign)
4164 self.assertEqual(d2._int, b2._int)
4165 self.assertEqual(d2._exp, b2._exp)
4166 else:
4167 eval("d1." + operation + "()")
4168 self.assertEqual(d1._sign, b1._sign)
4169 self.assertEqual(d1._int, b1._int)
4170 self.assertEqual(d1._exp, b1._exp)
4171 return
4172
4173 Decimal(d1)
4174 self.assertEqual(d1._sign, b1._sign)
4175 self.assertEqual(d1._int, b1._int)
4176 self.assertEqual(d1._exp, b1._exp)
4177
4178 checkSameDec("__abs__")
4179 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004180 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004181 checkSameDec("__eq__", True)
4182 checkSameDec("__ne__", True)
4183 checkSameDec("__le__", True)
4184 checkSameDec("__lt__", True)
4185 checkSameDec("__ge__", True)
4186 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004187 checkSameDec("__float__")
4188 checkSameDec("__floordiv__", True)
4189 checkSameDec("__hash__")
4190 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004191 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004192 checkSameDec("__mod__", True)
4193 checkSameDec("__mul__", True)
4194 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004195 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004196 checkSameDec("__pos__")
4197 checkSameDec("__pow__", True)
4198 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004199 checkSameDec("__rdivmod__", True)
4200 checkSameDec("__repr__")
4201 checkSameDec("__rfloordiv__", True)
4202 checkSameDec("__rmod__", True)
4203 checkSameDec("__rmul__", True)
4204 checkSameDec("__rpow__", True)
4205 checkSameDec("__rsub__", True)
4206 checkSameDec("__str__")
4207 checkSameDec("__sub__", True)
4208 checkSameDec("__truediv__", True)
4209 checkSameDec("adjusted")
4210 checkSameDec("as_tuple")
4211 checkSameDec("compare", True)
4212 checkSameDec("max", True)
4213 checkSameDec("min", True)
4214 checkSameDec("normalize")
4215 checkSameDec("quantize", True)
4216 checkSameDec("remainder_near", True)
4217 checkSameDec("same_quantum", True)
4218 checkSameDec("sqrt")
4219 checkSameDec("to_eng_string")
4220 checkSameDec("to_integral")
4221
Stefan Krah1919b7e2012-03-21 18:25:23 +01004222 def test_py_decimal_id(self):
4223 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004224
Stefan Krah1919b7e2012-03-21 18:25:23 +01004225 d = Decimal(45)
4226 e = Decimal(d)
4227 self.assertEqual(str(e), '45')
4228 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004229
Stefan Krah1919b7e2012-03-21 18:25:23 +01004230 def test_py_rescale(self):
4231 # Coverage
4232 Decimal = P.Decimal
4233 ROUND_UP = P.ROUND_UP
4234 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004235
Stefan Krah1919b7e2012-03-21 18:25:23 +01004236 with localcontext() as c:
4237 x = Decimal("NaN")._rescale(3, ROUND_UP)
4238 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004239
Stefan Krah1919b7e2012-03-21 18:25:23 +01004240 def test_py__round(self):
4241 # Coverage
4242 Decimal = P.Decimal
4243 ROUND_UP = P.ROUND_UP
Christian Heimes0348fb62008-03-26 12:55:56 +00004244
Stefan Krah1919b7e2012-03-21 18:25:23 +01004245 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004246
Stefan Krah1919b7e2012-03-21 18:25:23 +01004247class CFunctionality(unittest.TestCase):
4248 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004249
Stefan Krah1919b7e2012-03-21 18:25:23 +01004250 @requires_extra_functionality
4251 def test_c_ieee_context(self):
4252 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4253 IEEEContext = C.IEEEContext
4254 DECIMAL32 = C.DECIMAL32
4255 DECIMAL64 = C.DECIMAL64
4256 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004257
Stefan Krah1919b7e2012-03-21 18:25:23 +01004258 def assert_rest(self, context):
4259 self.assertEqual(context.clamp, 1)
4260 assert_signals(self, context, 'traps', [])
4261 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004262
Stefan Krah1919b7e2012-03-21 18:25:23 +01004263 c = IEEEContext(DECIMAL32)
4264 self.assertEqual(c.prec, 7)
4265 self.assertEqual(c.Emax, 96)
4266 self.assertEqual(c.Emin, -95)
4267 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004268
Stefan Krah1919b7e2012-03-21 18:25:23 +01004269 c = IEEEContext(DECIMAL64)
4270 self.assertEqual(c.prec, 16)
4271 self.assertEqual(c.Emax, 384)
4272 self.assertEqual(c.Emin, -383)
4273 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004274
Stefan Krah1919b7e2012-03-21 18:25:23 +01004275 c = IEEEContext(DECIMAL128)
4276 self.assertEqual(c.prec, 34)
4277 self.assertEqual(c.Emax, 6144)
4278 self.assertEqual(c.Emin, -6143)
4279 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004280
Stefan Krah1919b7e2012-03-21 18:25:23 +01004281 # Invalid values
4282 self.assertRaises(OverflowError, IEEEContext, 2**63)
4283 self.assertRaises(ValueError, IEEEContext, -1)
4284 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004285
Stefan Krah1919b7e2012-03-21 18:25:23 +01004286 @requires_extra_functionality
4287 def test_c_context(self):
4288 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004289
Stefan Krah1919b7e2012-03-21 18:25:23 +01004290 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4291 self.assertEqual(c._flags, C.DecClamped)
4292 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004293
Stefan Krah1919b7e2012-03-21 18:25:23 +01004294 @requires_extra_functionality
4295 def test_constants(self):
4296 # Condition flags
4297 cond = (
4298 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4299 C.DecDivisionImpossible, C.DecDivisionUndefined,
4300 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4301 C.DecInvalidOperation, C.DecMallocError,
4302 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4303 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004304 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004305
4306 # IEEEContext
4307 self.assertEqual(C.DECIMAL32, 32)
4308 self.assertEqual(C.DECIMAL64, 64)
4309 self.assertEqual(C.DECIMAL128, 128)
4310 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4311
4312 # Rounding modes
4313 for i, v in enumerate(RoundingModes[C]):
4314 self.assertEqual(v, i)
4315 self.assertEqual(C.ROUND_TRUNC, 8)
4316
4317 # Conditions
4318 for i, v in enumerate(cond):
4319 self.assertEqual(v, 1<<i)
4320
4321 self.assertEqual(C.DecIEEEInvalidOperation,
4322 C.DecConversionSyntax|
4323 C.DecDivisionImpossible|
4324 C.DecDivisionUndefined|
4325 C.DecFpuError|
4326 C.DecInvalidContext|
4327 C.DecInvalidOperation|
4328 C.DecMallocError)
4329
4330 self.assertEqual(C.DecErrors,
4331 C.DecIEEEInvalidOperation|
4332 C.DecDivisionByZero)
4333
4334 self.assertEqual(C.DecTraps,
4335 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4336
4337class CWhitebox(unittest.TestCase):
4338 """Whitebox testing for _decimal"""
4339
4340 def test_bignum(self):
4341 # Not exactly whitebox, but too slow with pydecimal.
4342
4343 Decimal = C.Decimal
4344 localcontext = C.localcontext
4345
4346 b1 = 10**35
4347 b2 = 10**36
4348 with localcontext() as c:
4349 c.prec = 1000000
4350 for i in range(5):
4351 a = random.randrange(b1, b2)
4352 b = random.randrange(1000, 1200)
4353 x = a ** b
4354 y = Decimal(a) ** Decimal(b)
4355 self.assertEqual(x, y)
4356
4357 def test_invalid_construction(self):
4358 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4359
4360 def test_c_input_restriction(self):
4361 # Too large for _decimal to be converted exactly
4362 Decimal = C.Decimal
4363 InvalidOperation = C.InvalidOperation
4364 Context = C.Context
4365 localcontext = C.localcontext
4366
4367 with localcontext(Context()):
4368 self.assertRaises(InvalidOperation, Decimal,
4369 "1e9999999999999999999")
4370
4371 def test_c_context_repr(self):
4372 # This test is _decimal-only because flags are not printed
4373 # in the same order.
4374 DefaultContext = C.DefaultContext
4375 FloatOperation = C.FloatOperation
4376 ROUND_HALF_DOWN = C.ROUND_HALF_DOWN
4377
4378 c = DefaultContext.copy()
4379
4380 c.prec = 425000000
4381 c.Emax = 425000000
4382 c.Emin = -425000000
4383 c.rounding = ROUND_HALF_DOWN
4384 c.capitals = 0
4385 c.clamp = 1
4386 for sig in OrderedSignals[C]:
4387 c.flags[sig] = True
4388 c.traps[sig] = True
4389 c.flags[FloatOperation] = True
4390 c.traps[FloatOperation] = True
4391
4392 s = c.__repr__()
4393 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4394 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4395 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4396 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4397 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4398 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4399 self.assertEqual(s, t)
4400
4401 def test_c_context_errors(self):
4402 Context = C.Context
4403 InvalidOperation = C.InvalidOperation
4404 Overflow = C.Overflow
4405 FloatOperation = C.FloatOperation
4406 localcontext = C.localcontext
4407 getcontext = C.getcontext
4408 setcontext = C.setcontext
4409 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4410
4411 c = Context()
4412
4413 # SignalDict: input validation
4414 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4415 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4416 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4417 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4418 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4419 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4420 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4421 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4422
4423 # Test assignment from a signal dict with the correct length but
4424 # one invalid key.
4425 d = c.flags.copy()
4426 del d[FloatOperation]
4427 d["XYZ"] = 91283719
4428 self.assertRaises(KeyError, setattr, c, 'flags', d)
4429 self.assertRaises(KeyError, setattr, c, 'traps', d)
4430
4431 # Input corner cases
4432 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4433 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4434
4435 # prec, Emax, Emin
4436 for attr in ['prec', 'Emax']:
4437 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4438 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4439
4440 # prec, Emax, Emin in context constructor
4441 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4442 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4443 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4444
4445 # Overflow in conversion
4446 self.assertRaises(OverflowError, Context, prec=int_max+1)
4447 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4448 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
4449 self.assertRaises(OverflowError, Context, rounding=int_max+1)
4450 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4451 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4452
4453 # OverflowError, general ValueError
4454 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4455 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4456 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4457 if sys.platform != 'win32':
4458 self.assertRaises(ValueError, setattr, c, attr, int_max)
4459 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4460
4461 # OverflowError, general TypeError
4462 for attr in ('rounding',):
4463 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4464 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4465 if sys.platform != 'win32':
4466 self.assertRaises(TypeError, setattr, c, attr, int_max)
4467 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4468
4469 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4470 if C.MAX_PREC == 425000000:
4471 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4472 int_max+1)
4473 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4474 int_max+1)
4475 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4476 -int_max-2)
4477
4478 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4479 if C.MAX_PREC == 425000000:
4480 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4481 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4482 1070000001)
4483 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4484 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4485 1070000001)
4486 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4487 -1070000001)
4488 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4489
4490 # capitals, clamp
4491 for attr in ['capitals', 'clamp']:
4492 self.assertRaises(ValueError, setattr, c, attr, -1)
4493 self.assertRaises(ValueError, setattr, c, attr, 2)
4494 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4495 if HAVE_CONFIG_64:
4496 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4497 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4498
4499 # Invalid local context
4500 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4501 locals())
4502
4503 # setcontext
4504 saved_context = getcontext()
4505 self.assertRaises(TypeError, setcontext, "xyz")
4506 setcontext(saved_context)
4507
4508 @requires_extra_functionality
4509 def test_c_context_errors_extra(self):
4510 Context = C.Context
4511 InvalidOperation = C.InvalidOperation
4512 Overflow = C.Overflow
4513 localcontext = C.localcontext
4514 getcontext = C.getcontext
4515 setcontext = C.setcontext
4516 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4517
4518 c = Context()
4519
4520 # Input corner cases
4521 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4522
4523 # OverflowError, general ValueError
4524 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4525 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4526 if sys.platform != 'win32':
4527 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4528 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4529
4530 # OverflowError, general TypeError
4531 for attr in ('_flags', '_traps'):
4532 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4533 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4534 if sys.platform != 'win32':
4535 self.assertRaises(TypeError, setattr, c, attr, int_max)
4536 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4537
4538 # _allcr
4539 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4540 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4541 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4542 if HAVE_CONFIG_64:
4543 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4544 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4545
4546 # _flags, _traps
4547 for attr in ['_flags', '_traps']:
4548 self.assertRaises(TypeError, setattr, c, attr, 999999)
4549 self.assertRaises(TypeError, setattr, c, attr, 'x')
4550
4551 def test_c_valid_context(self):
4552 # These tests are for code coverage in _decimal.
4553 DefaultContext = C.DefaultContext
4554 ROUND_HALF_UP = C.ROUND_HALF_UP
4555 Clamped = C.Clamped
4556 Underflow = C.Underflow
4557 Inexact = C.Inexact
4558 Rounded = C.Rounded
4559 Subnormal = C.Subnormal
4560
4561 c = DefaultContext.copy()
4562
4563 # Exercise all getters and setters
4564 c.prec = 34
4565 c.rounding = ROUND_HALF_UP
4566 c.Emax = 3000
4567 c.Emin = -3000
4568 c.capitals = 1
4569 c.clamp = 0
4570
4571 self.assertEqual(c.prec, 34)
4572 self.assertEqual(c.rounding, ROUND_HALF_UP)
4573 self.assertEqual(c.Emin, -3000)
4574 self.assertEqual(c.Emax, 3000)
4575 self.assertEqual(c.capitals, 1)
4576 self.assertEqual(c.clamp, 0)
4577
4578 self.assertEqual(c.Etiny(), -3033)
4579 self.assertEqual(c.Etop(), 2967)
4580
4581 # Exercise all unsafe setters
4582 if C.MAX_PREC == 425000000:
4583 c._unsafe_setprec(999999999)
4584 c._unsafe_setemax(999999999)
4585 c._unsafe_setemin(-999999999)
4586 self.assertEqual(c.prec, 999999999)
4587 self.assertEqual(c.Emax, 999999999)
4588 self.assertEqual(c.Emin, -999999999)
4589
4590 @requires_extra_functionality
4591 def test_c_valid_context_extra(self):
4592 DefaultContext = C.DefaultContext
4593
4594 c = DefaultContext.copy()
4595 self.assertEqual(c._allcr, 1)
4596 c._allcr = 0
4597 self.assertEqual(c._allcr, 0)
4598
4599 def test_c_round(self):
4600 # Restricted input.
4601 Decimal = C.Decimal
4602 InvalidOperation = C.InvalidOperation
4603 localcontext = C.localcontext
4604 MAX_EMAX = C.MAX_EMAX
4605 MIN_ETINY = C.MIN_ETINY
4606 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4607
4608 with localcontext() as c:
4609 c.traps[InvalidOperation] = True
4610 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4611 -int_max-1)
4612 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4613 int_max)
4614 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4615 int(MAX_EMAX+1))
4616 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4617 -int(MIN_ETINY-1))
4618 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4619 -int_max-2)
4620 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4621 int_max+1)
4622
4623 def test_c_format(self):
4624 # Restricted input
4625 Decimal = C.Decimal
4626 InvalidOperation = C.InvalidOperation
4627 Rounded = C.Rounded
4628 localcontext = C.localcontext
4629 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4630
4631 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4632 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4633 self.assertRaises(TypeError, Decimal(1).__format__, [])
4634
4635 with localcontext() as c:
4636 c.traps[InvalidOperation] = True
4637 c.traps[Rounded] = True
4638 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4639 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4640 self.assertRaises(InvalidOperation, Decimal("1.23456789").__format__,
4641 "=%d.1" % maxsize)
4642
4643 def test_c_integral(self):
4644 Decimal = C.Decimal
4645 Inexact = C.Inexact
4646 ROUND_UP = C.ROUND_UP
4647 localcontext = C.localcontext
4648
4649 x = Decimal(10)
4650 self.assertEqual(x.to_integral(), 10)
4651 self.assertRaises(TypeError, x.to_integral, '10')
4652 self.assertRaises(TypeError, x.to_integral, 10, 'x')
4653 self.assertRaises(TypeError, x.to_integral, 10)
4654
4655 self.assertEqual(x.to_integral_value(), 10)
4656 self.assertRaises(TypeError, x.to_integral_value, '10')
4657 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
4658 self.assertRaises(TypeError, x.to_integral_value, 10)
4659
4660 self.assertEqual(x.to_integral_exact(), 10)
4661 self.assertRaises(TypeError, x.to_integral_exact, '10')
4662 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
4663 self.assertRaises(TypeError, x.to_integral_exact, 10)
4664
4665 with localcontext() as c:
4666 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
4667 self.assertEqual(x, Decimal('100000000000000000000000000'))
4668
4669 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
4670 self.assertEqual(x, Decimal('100000000000000000000000000'))
4671
4672 c.traps[Inexact] = True
4673 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
4674
4675 def test_c_funcs(self):
4676 # Invalid arguments
4677 Decimal = C.Decimal
4678 InvalidOperation = C.InvalidOperation
4679 DivisionByZero = C.DivisionByZero
4680 ROUND_UP = C.ROUND_UP
4681 getcontext = C.getcontext
4682 localcontext = C.localcontext
4683
4684 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
4685
4686 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
4687 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
4688 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
4689
Raymond Hettinger771ed762009-01-03 19:20:32 +00004690 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01004691 TypeError,
4692 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00004693 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004694 self.assertRaises(
4695 TypeError,
4696 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
4697 )
4698 self.assertRaises(
4699 TypeError,
4700 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
4701 )
4702 self.assertRaises(
4703 TypeError,
4704 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
4705 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00004706
Stefan Krah1919b7e2012-03-21 18:25:23 +01004707 with localcontext() as c:
4708 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004709
Stefan Krah1919b7e2012-03-21 18:25:23 +01004710 # Invalid arguments
4711 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
4712 self.assertRaises(TypeError, c.canonical, 200)
4713 self.assertRaises(TypeError, c.is_canonical, 200)
4714 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
4715 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004716
Stefan Krah1919b7e2012-03-21 18:25:23 +01004717 self.assertEqual(str(c.canonical(Decimal(200))), '200')
4718 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00004719
Stefan Krah1919b7e2012-03-21 18:25:23 +01004720 c.traps[DivisionByZero] = True
4721 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
4722 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
4723 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00004724
Stefan Krah1919b7e2012-03-21 18:25:23 +01004725 c.clear_flags()
4726 c.traps[InvalidOperation] = True
4727 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
4728 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
4729 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00004730
Stefan Krah1919b7e2012-03-21 18:25:23 +01004731 c.traps[InvalidOperation] = True
4732 c.prec = 2
4733 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00004734
Stefan Krah1919b7e2012-03-21 18:25:23 +01004735 @requires_extra_functionality
4736 def test_c_context_templates(self):
4737 self.assertEqual(
4738 C.BasicContext._traps,
4739 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
4740 C.DecUnderflow|C.DecClamped
4741 )
4742 self.assertEqual(
4743 C.DefaultContext._traps,
4744 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
4745 )
Mark Dickinson84230a12010-02-18 14:49:50 +00004746
Stefan Krah1919b7e2012-03-21 18:25:23 +01004747 @requires_extra_functionality
4748 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00004749
Stefan Krah1919b7e2012-03-21 18:25:23 +01004750 # SignalDict coverage
4751 Context = C.Context
4752 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00004753
Stefan Krah1919b7e2012-03-21 18:25:23 +01004754 InvalidOperation = C.InvalidOperation
4755 DivisionByZero = C.DivisionByZero
4756 Overflow = C.Overflow
4757 Subnormal = C.Subnormal
4758 Underflow = C.Underflow
4759 Rounded = C.Rounded
4760 Inexact = C.Inexact
4761 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00004762
Stefan Krah1919b7e2012-03-21 18:25:23 +01004763 DecClamped = C.DecClamped
4764 DecInvalidOperation = C.DecInvalidOperation
4765 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00004766
Stefan Krah1919b7e2012-03-21 18:25:23 +01004767 def assertIsExclusivelySet(signal, signal_dict):
4768 for sig in signal_dict:
4769 if sig == signal:
4770 self.assertTrue(signal_dict[sig])
4771 else:
4772 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00004773
Stefan Krah1919b7e2012-03-21 18:25:23 +01004774 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00004775
Stefan Krah1919b7e2012-03-21 18:25:23 +01004776 # Signal dict methods
4777 self.assertTrue(Overflow in c.traps)
4778 c.clear_traps()
4779 for k in c.traps.keys():
4780 c.traps[k] = True
4781 for v in c.traps.values():
4782 self.assertTrue(v)
4783 c.clear_traps()
4784 for k, v in c.traps.items():
4785 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00004786
Stefan Krah1919b7e2012-03-21 18:25:23 +01004787 self.assertFalse(c.flags.get(Overflow))
4788 self.assertIs(c.flags.get("x"), None)
4789 self.assertEqual(c.flags.get("x", "y"), "y")
4790 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00004791
Stefan Krah1919b7e2012-03-21 18:25:23 +01004792 self.assertEqual(len(c.flags), len(c.traps))
4793 s = sys.getsizeof(c.flags)
4794 s = sys.getsizeof(c.traps)
4795 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00004796
Stefan Krah1919b7e2012-03-21 18:25:23 +01004797 # Set flags/traps.
4798 c.clear_flags()
4799 c._flags = DecClamped
4800 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00004801
Stefan Krah1919b7e2012-03-21 18:25:23 +01004802 c.clear_traps()
4803 c._traps = DecInvalidOperation
4804 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00004805
Stefan Krah1919b7e2012-03-21 18:25:23 +01004806 # Set flags/traps from dictionary.
4807 c.clear_flags()
4808 d = c.flags.copy()
4809 d[DivisionByZero] = True
4810 c.flags = d
4811 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004812
Stefan Krah1919b7e2012-03-21 18:25:23 +01004813 c.clear_traps()
4814 d = c.traps.copy()
4815 d[Underflow] = True
4816 c.traps = d
4817 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004818
Stefan Krah1919b7e2012-03-21 18:25:23 +01004819 # Random constructors
4820 IntSignals = {
4821 Clamped: C.DecClamped,
4822 Rounded: C.DecRounded,
4823 Inexact: C.DecInexact,
4824 Subnormal: C.DecSubnormal,
4825 Underflow: C.DecUnderflow,
4826 Overflow: C.DecOverflow,
4827 DivisionByZero: C.DecDivisionByZero,
4828 InvalidOperation: C.DecIEEEInvalidOperation
4829 }
4830 IntCond = [
4831 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
4832 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
4833 C.DecConversionSyntax,
4834 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01004835
Stefan Krah1919b7e2012-03-21 18:25:23 +01004836 lim = len(OrderedSignals[C])
4837 for r in range(lim):
4838 for t in range(lim):
4839 for round in RoundingModes[C]:
4840 flags = random.sample(OrderedSignals[C], r)
4841 traps = random.sample(OrderedSignals[C], t)
4842 prec = random.randrange(1, 10000)
4843 emin = random.randrange(-10000, 0)
4844 emax = random.randrange(0, 10000)
4845 clamp = random.randrange(0, 2)
4846 caps = random.randrange(0, 2)
4847 cr = random.randrange(0, 2)
4848 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
4849 capitals=caps, clamp=clamp, flags=list(flags),
4850 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00004851
Stefan Krah1919b7e2012-03-21 18:25:23 +01004852 self.assertEqual(c.prec, prec)
4853 self.assertEqual(c.rounding, round)
4854 self.assertEqual(c.Emin, emin)
4855 self.assertEqual(c.Emax, emax)
4856 self.assertEqual(c.capitals, caps)
4857 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00004858
Stefan Krah1919b7e2012-03-21 18:25:23 +01004859 f = 0
4860 for x in flags:
4861 f |= IntSignals[x]
4862 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004863
Stefan Krah1919b7e2012-03-21 18:25:23 +01004864 f = 0
4865 for x in traps:
4866 f |= IntSignals[x]
4867 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004868
Stefan Krah1919b7e2012-03-21 18:25:23 +01004869 for cond in IntCond:
4870 c._flags = cond
4871 self.assertTrue(c._flags&DecIEEEInvalidOperation)
4872 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004873
Stefan Krah1919b7e2012-03-21 18:25:23 +01004874 for cond in IntCond:
4875 c._traps = cond
4876 self.assertTrue(c._traps&DecIEEEInvalidOperation)
4877 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004878
Stefan Krah1919b7e2012-03-21 18:25:23 +01004879 def test_invalid_override(self):
4880 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00004881
Stefan Krah1919b7e2012-03-21 18:25:23 +01004882 try:
4883 from locale import CHAR_MAX
4884 except ImportError:
4885 return
Mark Dickinson84230a12010-02-18 14:49:50 +00004886
Stefan Krah1919b7e2012-03-21 18:25:23 +01004887 def make_grouping(lst):
4888 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00004889
Stefan Krah1919b7e2012-03-21 18:25:23 +01004890 def get_fmt(x, override=None, fmt='n'):
4891 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004892
Stefan Krah1919b7e2012-03-21 18:25:23 +01004893 invalid_grouping = {
4894 'decimal_point' : ',',
4895 'grouping' : make_grouping([255, 255, 0]),
4896 'thousands_sep' : ','
4897 }
4898 invalid_dot = {
4899 'decimal_point' : 'xxxxx',
4900 'grouping' : make_grouping([3, 3, 0]),
4901 'thousands_sep' : ','
4902 }
4903 invalid_sep = {
4904 'decimal_point' : '.',
4905 'grouping' : make_grouping([3, 3, 0]),
4906 'thousands_sep' : 'yyyyy'
4907 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004908
Stefan Krah1919b7e2012-03-21 18:25:23 +01004909 if CHAR_MAX == 127: # negative grouping in override
4910 self.assertRaises(ValueError, get_fmt, 12345,
4911 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004912
Stefan Krah1919b7e2012-03-21 18:25:23 +01004913 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
4914 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004915
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004916
Stefan Krah1919b7e2012-03-21 18:25:23 +01004917all_tests = [
4918 CExplicitConstructionTest, PyExplicitConstructionTest,
4919 CImplicitConstructionTest, PyImplicitConstructionTest,
4920 CFormatTest, PyFormatTest,
4921 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
4922 CThreadingTest, PyThreadingTest,
4923 CUsabilityTest, PyUsabilityTest,
4924 CPythonAPItests, PyPythonAPItests,
4925 CContextAPItests, PyContextAPItests,
4926 CContextWithStatement, PyContextWithStatement,
4927 CContextFlags, PyContextFlags,
4928 CSpecialContexts, PySpecialContexts,
4929 CContextInputValidation, PyContextInputValidation,
4930 CContextSubclassing, PyContextSubclassing,
4931 CCoverage, PyCoverage,
4932 CFunctionality, PyFunctionality,
4933 CWhitebox, PyWhitebox,
4934 CIBMTestCases, PyIBMTestCases,
4935]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004936
Stefan Krah1919b7e2012-03-21 18:25:23 +01004937# Delete C tests if _decimal.so is not present.
4938if not C:
4939 all_tests = all_tests[1::2]
4940else:
4941 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004942
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004943
4944def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004945 """ Execute the tests.
4946
Raymond Hettingered20ad82004-09-04 20:09:13 +00004947 Runs all arithmetic tests if arith is True or if the "decimal" resource
4948 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004949 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00004950
Stefan Krah1919b7e2012-03-21 18:25:23 +01004951 init(C)
4952 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004953 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00004954 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004955 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00004956
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004957 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01004958 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004959 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01004960 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004961
4962 # Dynamically build custom test definition for each file in the test
4963 # directory and add the definitions to the DecimalTest class. This
4964 # procedure insures that new files do not get skipped.
4965 for filename in os.listdir(directory):
4966 if '.decTest' not in filename or filename.startswith("."):
4967 continue
4968 head, tail = filename.split('.')
4969 if todo_tests is not None and head not in todo_tests:
4970 continue
4971 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004972 setattr(CIBMTestCases, 'test_' + head, tester)
4973 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004974 del filename, head, tail, tester
4975
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004976
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00004977 try:
4978 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004979 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01004980 from doctest import IGNORE_EXCEPTION_DETAIL
4981 savedecimal = sys.modules['decimal']
4982 if C:
4983 sys.modules['decimal'] = C
4984 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
4985 sys.modules['decimal'] = P
4986 run_doctest(P, verbose)
4987 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00004988 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01004989 if C: C.setcontext(ORIGINAL_CONTEXT[C])
4990 P.setcontext(ORIGINAL_CONTEXT[P])
4991 if not C:
4992 warnings.warn('C tests skipped: no module named _decimal.',
4993 UserWarning)
4994 if not orig_sys_decimal is sys.modules['decimal']:
4995 raise TestFailed("Internal error: unbalanced number of changes to "
4996 "sys.modules['decimal'].")
4997
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004998
4999if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005000 import optparse
5001 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5002 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5003 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5004 (opt, args) = p.parse_args()
5005
5006 if opt.skip:
5007 test_main(arith=False, verbose=True)
5008 elif args:
5009 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005010 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005011 test_main(arith=True, verbose=True)