blob: a178f6f3ccf75da55ff5d9d2b7cba23e7960fe35 [file] [log] [blame]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001# Copyright (c) 2004 Python Software Foundation.
2# All rights reserved.
3
4# Written by Eric Price <eprice at tjhsst.edu>
5# and Facundo Batista <facundo at taniquetil.com.ar>
6# and Raymond Hettinger <python at rcn.com>
7# and Aahz (aahz at pobox.com)
8# and Tim Peters
9
10"""
11These are the test cases for the Decimal module.
12
13There are two groups of tests, Arithmetic and Behaviour. The former test
14the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
15test the pythonic behaviour according to PEP 327.
16
17Cowlishaw's tests can be downloaded from:
18
Stefan Krah1919b7e2012-03-21 18:25:23 +010019 http://speleotrove.com/decimal/dectest.zip
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000020
21This test module can be called from command line with one parameter (Arithmetic
22or Behaviour) to test each part, or without parameter to test both parts. If
23you're working through IDLE, you can import this test module and call test_main()
24with the corresponding argument.
25"""
26
Christian Heimes400adb02008-02-01 08:12:03 +000027import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000028import os, sys
Mark Dickinsonac256ab2010-04-03 11:08:14 +000029import operator
Mark Dickinsonb1d8e322010-05-22 18:35:36 +000030import warnings
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000031import pickle, copy
Christian Heimes400adb02008-02-01 08:12:03 +000032import unittest
Raymond Hettinger82417ca2009-02-03 03:54:28 +000033import numbers
Stefan Krah1919b7e2012-03-21 18:25:23 +010034import locale
Eric Smith3ab08ca2010-12-04 15:17:38 +000035from test.support import (run_unittest, run_doctest, is_resource_enabled,
36 requires_IEEE_754)
Stefan Krah6fb204a2012-09-28 16:18:54 +020037from test.support import (check_warnings, import_fresh_module, TestFailed,
Stefan Krah6e467042012-11-10 23:09:04 +010038 run_with_locale, cpython_only)
Raymond Hettinger0aeac102004-07-05 22:53:03 +000039import random
Stefan Krah1919b7e2012-03-21 18:25:23 +010040import time
41import warnings
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000042try:
43 import threading
44except ImportError:
45 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000046
Raymond Hettingerfed52962004-07-14 15:41:57 +000047
Stefan Krah1919b7e2012-03-21 18:25:23 +010048C = import_fresh_module('decimal', fresh=['_decimal'])
49P = import_fresh_module('decimal', blocked=['_decimal'])
50orig_sys_decimal = sys.modules['decimal']
51
52# fractions module must import the correct decimal module.
53cfractions = import_fresh_module('fractions', fresh=['fractions'])
54sys.modules['decimal'] = P
55pfractions = import_fresh_module('fractions', fresh=['fractions'])
56sys.modules['decimal'] = C
57fractions = {C:cfractions, P:pfractions}
58sys.modules['decimal'] = orig_sys_decimal
59
60
61# Useful Test Constant
62Signals = {
63 C: tuple(C.getcontext().flags.keys()) if C else None,
64 P: tuple(P.getcontext().flags.keys())
65}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000066# Signals ordered with respect to precedence: when an operation
67# produces multiple signals, signals occurring later in the list
68# should be handled before those occurring earlier in the list.
Stefan Krah1919b7e2012-03-21 18:25:23 +010069OrderedSignals = {
70 C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow,
71 C.Overflow, C.DivisionByZero, C.InvalidOperation,
72 C.FloatOperation] if C else None,
73 P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow,
74 P.Overflow, P.DivisionByZero, P.InvalidOperation,
75 P.FloatOperation]
76}
77def assert_signals(cls, context, attr, expected):
78 d = getattr(context, attr)
79 cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
80
Stefan Krah59a4a932013-01-16 12:58:59 +010081ROUND_UP = P.ROUND_UP
82ROUND_DOWN = P.ROUND_DOWN
83ROUND_CEILING = P.ROUND_CEILING
84ROUND_FLOOR = P.ROUND_FLOOR
85ROUND_HALF_UP = P.ROUND_HALF_UP
86ROUND_HALF_DOWN = P.ROUND_HALF_DOWN
87ROUND_HALF_EVEN = P.ROUND_HALF_EVEN
88ROUND_05UP = P.ROUND_05UP
89
90RoundingModes = [
91 ROUND_UP, ROUND_DOWN, ROUND_CEILING, ROUND_FLOOR,
92 ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
93 ROUND_05UP
94]
Mark Dickinsonc69160e2010-05-04 14:35:33 +000095
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000096# Tests are built around these assumed context defaults.
97# test_main() restores the original context.
Stefan Krah1919b7e2012-03-21 18:25:23 +010098ORIGINAL_CONTEXT = {
99 C: C.getcontext().copy() if C else None,
100 P: P.getcontext().copy()
101}
102def init(m):
103 if not m: return
104 DefaultTestContext = m.Context(
Stefan Krah59a4a932013-01-16 12:58:59 +0100105 prec=9, rounding=ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100106 )
107 m.setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +0000108
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000109TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000110if __name__ == '__main__':
111 file = sys.argv[0]
112else:
113 file = __file__
114testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +0000115directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000116
Raymond Hettinger267b8682005-03-27 10:47:39 +0000117skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000118
119# Make sure it actually raises errors when not expected and caught in flags
120# Slower, since it runs some things several times.
121EXTENDEDERRORTEST = False
122
Stefan Krah1919b7e2012-03-21 18:25:23 +0100123# Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
124EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
125requires_extra_functionality = unittest.skipUnless(
126 EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
127skip_if_extra_functionality = unittest.skipIf(
128 EXTRA_FUNCTIONALITY, "test requires regular build")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000129
130
Stefan Krah1919b7e2012-03-21 18:25:23 +0100131class IBMTestCases(unittest.TestCase):
132 """Class which tests the Decimal class against the IBM test cases."""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000133
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000134 def setUp(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100135 self.context = self.decimal.Context()
136 self.readcontext = self.decimal.Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000137 self.ignore_list = ['#']
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000138
Stefan Krah1919b7e2012-03-21 18:25:23 +0100139 # List of individual .decTest test ids that correspond to tests that
140 # we're skipping for one reason or another.
141 self.skipped_test_ids = set([
142 # Skip implementation-specific scaleb tests.
143 'scbx164',
144 'scbx165',
145
146 # For some operations (currently exp, ln, log10, power), the decNumber
147 # reference implementation imposes additional restrictions on the context
148 # and operands. These restrictions are not part of the specification;
149 # however, the effect of these restrictions does show up in some of the
150 # testcases. We skip testcases that violate these restrictions, since
151 # Decimal behaves differently from decNumber for these testcases so these
152 # testcases would otherwise fail.
153 'expx901',
154 'expx902',
155 'expx903',
156 'expx905',
157 'lnx901',
158 'lnx902',
159 'lnx903',
160 'lnx905',
161 'logx901',
162 'logx902',
163 'logx903',
164 'logx905',
165 'powx1183',
166 'powx1184',
167 'powx4001',
168 'powx4002',
169 'powx4003',
170 'powx4005',
171 'powx4008',
172 'powx4010',
173 'powx4012',
174 'powx4014',
175 ])
176
177 if self.decimal == C:
178 # status has additional Subnormal, Underflow
179 self.skipped_test_ids.add('pwsx803')
180 self.skipped_test_ids.add('pwsx805')
181 # Correct rounding (skipped for decNumber, too)
182 self.skipped_test_ids.add('powx4302')
183 self.skipped_test_ids.add('powx4303')
184 self.skipped_test_ids.add('powx4342')
185 self.skipped_test_ids.add('powx4343')
186 # http://bugs.python.org/issue7049
187 self.skipped_test_ids.add('pwmx325')
188 self.skipped_test_ids.add('pwmx326')
189
190 # Map test directives to setter functions.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000191 self.ChangeDict = {'precision' : self.change_precision,
Stefan Krah1919b7e2012-03-21 18:25:23 +0100192 'rounding' : self.change_rounding_method,
193 'maxexponent' : self.change_max_exponent,
194 'minexponent' : self.change_min_exponent,
195 'clamp' : self.change_clamp}
196
197 # Name adapter to be able to change the Decimal and Context
198 # interface without changing the test files from Cowlishaw.
199 self.NameAdapter = {'and':'logical_and',
200 'apply':'_apply',
201 'class':'number_class',
202 'comparesig':'compare_signal',
203 'comparetotal':'compare_total',
204 'comparetotmag':'compare_total_mag',
205 'copy':'copy_decimal',
206 'copyabs':'copy_abs',
207 'copynegate':'copy_negate',
208 'copysign':'copy_sign',
209 'divideint':'divide_int',
210 'invert':'logical_invert',
211 'iscanonical':'is_canonical',
212 'isfinite':'is_finite',
213 'isinfinite':'is_infinite',
214 'isnan':'is_nan',
215 'isnormal':'is_normal',
216 'isqnan':'is_qnan',
217 'issigned':'is_signed',
218 'issnan':'is_snan',
219 'issubnormal':'is_subnormal',
220 'iszero':'is_zero',
221 'maxmag':'max_mag',
222 'minmag':'min_mag',
223 'nextminus':'next_minus',
224 'nextplus':'next_plus',
225 'nexttoward':'next_toward',
226 'or':'logical_or',
227 'reduce':'normalize',
228 'remaindernear':'remainder_near',
229 'samequantum':'same_quantum',
230 'squareroot':'sqrt',
231 'toeng':'to_eng_string',
232 'tointegral':'to_integral_value',
233 'tointegralx':'to_integral_exact',
234 'tosci':'to_sci_string',
235 'xor':'logical_xor'}
236
237 # Map test-case names to roundings.
Stefan Krah59a4a932013-01-16 12:58:59 +0100238 self.RoundingDict = {'ceiling' : ROUND_CEILING,
239 'down' : ROUND_DOWN,
240 'floor' : ROUND_FLOOR,
241 'half_down' : ROUND_HALF_DOWN,
242 'half_even' : ROUND_HALF_EVEN,
243 'half_up' : ROUND_HALF_UP,
244 'up' : ROUND_UP,
245 '05up' : ROUND_05UP}
Stefan Krah1919b7e2012-03-21 18:25:23 +0100246
247 # Map the test cases' error names to the actual errors.
248 self.ErrorNames = {'clamped' : self.decimal.Clamped,
249 'conversion_syntax' : self.decimal.InvalidOperation,
250 'division_by_zero' : self.decimal.DivisionByZero,
251 'division_impossible' : self.decimal.InvalidOperation,
252 'division_undefined' : self.decimal.InvalidOperation,
253 'inexact' : self.decimal.Inexact,
254 'invalid_context' : self.decimal.InvalidOperation,
255 'invalid_operation' : self.decimal.InvalidOperation,
256 'overflow' : self.decimal.Overflow,
257 'rounded' : self.decimal.Rounded,
258 'subnormal' : self.decimal.Subnormal,
259 'underflow' : self.decimal.Underflow}
260
261 # The following functions return True/False rather than a
262 # Decimal instance.
263 self.LogicalFunctions = ('is_canonical',
264 'is_finite',
265 'is_infinite',
266 'is_nan',
267 'is_normal',
268 'is_qnan',
269 'is_signed',
270 'is_snan',
271 'is_subnormal',
272 'is_zero',
273 'same_quantum')
274
275 def read_unlimited(self, v, context):
276 """Work around the limitations of the 32-bit _decimal version. The
277 guaranteed maximum values for prec, Emax etc. are 425000000,
278 but higher values usually work, except for rare corner cases.
279 In particular, all of the IBM tests pass with maximum values
280 of 1070000000."""
281 if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
282 self.readcontext._unsafe_setprec(1070000000)
283 self.readcontext._unsafe_setemax(1070000000)
284 self.readcontext._unsafe_setemin(-1070000000)
285 return self.readcontext.create_decimal(v)
286 else:
287 return self.decimal.Decimal(v, context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000288
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000289 def eval_file(self, file):
290 global skip_expected
291 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000292 raise unittest.SkipTest
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000293 with open(file) as f:
294 for line in f:
295 line = line.replace('\r\n', '').replace('\n', '')
296 #print line
297 try:
298 t = self.eval_line(line)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100299 except self.decimal.DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200300 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000301 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000302
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000303
304 def eval_line(self, s):
305 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
306 s = (s.split('->')[0] + '->' +
307 s.split('->')[1].split('--')[0]).strip()
308 else:
309 s = s.split('--')[0].strip()
310
311 for ignore in self.ignore_list:
312 if s.find(ignore) >= 0:
313 #print s.split()[0], 'NotImplemented--', ignore
314 return
315 if not s:
316 return
317 elif ':' in s:
318 return self.eval_directive(s)
319 else:
320 return self.eval_equation(s)
321
322 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000323 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000324 if funct == 'rounding':
Stefan Krah1919b7e2012-03-21 18:25:23 +0100325 value = self.RoundingDict[value]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000326 else:
327 try:
328 value = int(value)
329 except ValueError:
330 pass
331
Stefan Krah1919b7e2012-03-21 18:25:23 +0100332 funct = self.ChangeDict.get(funct, (lambda *args: None))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000333 funct(value)
334
335 def eval_equation(self, s):
Raymond Hettingered20ad82004-09-04 20:09:13 +0000336
337 if not TEST_ALL and random.random() < 0.90:
338 return
339
Stefan Krah1919b7e2012-03-21 18:25:23 +0100340 self.context.clear_flags()
341
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000342 try:
343 Sides = s.split('->')
344 L = Sides[0].strip().split()
345 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000346 if DEBUG:
347 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000348 funct = L[1].lower()
349 valstemp = L[2:]
350 L = Sides[1].strip().split()
351 ans = L[0]
352 exceptions = L[1:]
353 except (TypeError, AttributeError, IndexError):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100354 raise self.decimal.InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000355 def FixQuotes(val):
356 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
357 val = val.replace("'", '').replace('"', '')
358 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
359 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000360
Stefan Krah1919b7e2012-03-21 18:25:23 +0100361 if id in self.skipped_test_ids:
Mark Dickinson8a546532009-10-08 16:30:38 +0000362 return
363
Stefan Krah1919b7e2012-03-21 18:25:23 +0100364 fname = self.NameAdapter.get(funct, funct)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000365 if fname == 'rescale':
366 return
367 funct = getattr(self.context, fname)
368 vals = []
369 conglomerate = ''
370 quote = 0
Stefan Krah1919b7e2012-03-21 18:25:23 +0100371 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000372
Stefan Krah1919b7e2012-03-21 18:25:23 +0100373 for exception in Signals[self.decimal]:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000374 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000375 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000376 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000377 for i, val in enumerate(valstemp):
378 if val.count("'") % 2 == 1:
379 quote = 1 - quote
380 if quote:
381 conglomerate = conglomerate + ' ' + val
382 continue
383 else:
384 val = conglomerate + val
385 conglomerate = ''
386 v = FixQuotes(val)
387 if fname in ('to_sci_string', 'to_eng_string'):
388 if EXTENDEDERRORTEST:
389 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000390 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000391 try:
392 funct(self.context.create_decimal(v))
393 except error:
394 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100395 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000396 self.fail("Raised %s in %s when %s disabled" % \
397 (e, s, error))
398 else:
399 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000400 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000401 v = self.context.create_decimal(v)
402 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +0100403 v = self.read_unlimited(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000404 vals.append(v)
405
406 ans = FixQuotes(ans)
407
408 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
409 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000410 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000411 try:
412 funct(*vals)
413 except error:
414 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100415 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000416 self.fail("Raised %s in %s when %s disabled" % \
417 (e, s, error))
418 else:
419 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000420 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000421
422 # as above, but add traps cumulatively, to check precedence
Stefan Krah1919b7e2012-03-21 18:25:23 +0100423 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions]
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000424 for error in ordered_errors:
425 self.context.traps[error] = 1
426 try:
427 funct(*vals)
428 except error:
429 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100430 except Signals[self.decimal] as e:
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000431 self.fail("Raised %s in %s; expected %s" %
432 (type(e), s, error))
433 else:
434 self.fail("Did not raise %s in %s" % (error, s))
435 # reset traps
436 for error in ordered_errors:
437 self.context.traps[error] = 0
438
439
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000440 if DEBUG:
441 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000442 try:
443 result = str(funct(*vals))
Stefan Krah1919b7e2012-03-21 18:25:23 +0100444 if fname in self.LogicalFunctions:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000445 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Stefan Krah1919b7e2012-03-21 18:25:23 +0100446 except Signals[self.decimal] as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000447 self.fail("Raised %s in %s" % (error, s))
448 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000449 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000450 raise
451
452 myexceptions = self.getexceptions()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000453
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000454 myexceptions.sort(key=repr)
455 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000456
457 self.assertEqual(result, ans,
458 'Incorrect answer for ' + s + ' -- got ' + result)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100459
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000460 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000461 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000462
463 def getexceptions(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100464 return [e for e in Signals[self.decimal] if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000465
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000466 def change_precision(self, prec):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100467 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
468 self.context._unsafe_setprec(prec)
469 else:
470 self.context.prec = prec
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000471 def change_rounding_method(self, rounding):
472 self.context.rounding = rounding
473 def change_min_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100474 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
475 self.context._unsafe_setemin(exp)
476 else:
477 self.context.Emin = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000478 def change_max_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100479 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
480 self.context._unsafe_setemax(exp)
481 else:
482 self.context.Emax = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000483 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000484 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000485
Stefan Krah1919b7e2012-03-21 18:25:23 +0100486class CIBMTestCases(IBMTestCases):
487 decimal = C
488class PyIBMTestCases(IBMTestCases):
489 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000490
491# The following classes test the behaviour of Decimal according to PEP 327
492
Stefan Krah1919b7e2012-03-21 18:25:23 +0100493class ExplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000494 '''Unit tests for Explicit Construction cases of Decimal.'''
495
496 def test_explicit_empty(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100497 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000498 self.assertEqual(Decimal(), Decimal("0"))
499
500 def test_explicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100501 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000502 self.assertRaises(TypeError, Decimal, None)
503
504 def test_explicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100505 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000506
507 #positive
508 d = Decimal(45)
509 self.assertEqual(str(d), '45')
510
511 #very large positive
512 d = Decimal(500000123)
513 self.assertEqual(str(d), '500000123')
514
515 #negative
516 d = Decimal(-45)
517 self.assertEqual(str(d), '-45')
518
519 #zero
520 d = Decimal(0)
521 self.assertEqual(str(d), '0')
522
Stefan Krah1919b7e2012-03-21 18:25:23 +0100523 # single word longs
524 for n in range(0, 32):
525 for sign in (-1, 1):
526 for x in range(-5, 5):
527 i = sign * (2**n + x)
528 d = Decimal(i)
529 self.assertEqual(str(d), str(i))
530
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000531 def test_explicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100532 Decimal = self.decimal.Decimal
533 InvalidOperation = self.decimal.InvalidOperation
534 localcontext = self.decimal.localcontext
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000535
536 #empty
537 self.assertEqual(str(Decimal('')), 'NaN')
538
539 #int
540 self.assertEqual(str(Decimal('45')), '45')
541
542 #float
543 self.assertEqual(str(Decimal('45.34')), '45.34')
544
545 #engineer notation
546 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
547
548 #just not a number
549 self.assertEqual(str(Decimal('ugly')), 'NaN')
550
Christian Heimesa62da1d2008-01-12 19:39:10 +0000551 #leading and trailing whitespace permitted
552 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
553 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
Stefan Krah1919b7e2012-03-21 18:25:23 +0100554 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
555
556 # unicode whitespace
557 for lead in ["", ' ', '\u00a0', '\u205f']:
558 for trail in ["", ' ', '\u00a0', '\u205f']:
559 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
560 '9.311E+28')
561
562 with localcontext() as c:
563 c.traps[InvalidOperation] = True
564 # Invalid string
565 self.assertRaises(InvalidOperation, Decimal, "xyz")
566 # Two arguments max
567 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
568
569 # space within the numeric part
570 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
571 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
572
573 # unicode whitespace
574 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
575 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
576
577 # embedded NUL
578 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
579
Stefan Krah6e467042012-11-10 23:09:04 +0100580 @cpython_only
581 def test_from_legacy_strings(self):
582 import _testcapi
583 Decimal = self.decimal.Decimal
584 context = self.decimal.Context()
585
586 s = _testcapi.unicode_legacy_string('9.999999')
587 self.assertEqual(str(Decimal(s)), '9.999999')
588 self.assertEqual(str(context.create_decimal(s)), '9.999999')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000589
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000590 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100591 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000592
593 #zero
594 d = Decimal( (0, (0,), 0) )
595 self.assertEqual(str(d), '0')
596
597 #int
598 d = Decimal( (1, (4, 5), 0) )
599 self.assertEqual(str(d), '-45')
600
601 #float
602 d = Decimal( (0, (4, 5, 3, 4), -2) )
603 self.assertEqual(str(d), '45.34')
604
605 #weird
606 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
607 self.assertEqual(str(d), '-4.34913534E-17')
608
Stefan Krah1919b7e2012-03-21 18:25:23 +0100609 #inf
610 d = Decimal( (0, (), "F") )
611 self.assertEqual(str(d), 'Infinity')
612
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000613 #wrong number of items
614 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
615
616 #bad sign
617 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000618 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
619 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000620
621 #bad exp
622 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000623 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
624 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000625
626 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100627 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000628 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
629 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000630 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000631 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000632
Stefan Krah1919b7e2012-03-21 18:25:23 +0100633 def test_explicit_from_list(self):
634 Decimal = self.decimal.Decimal
635
636 d = Decimal([0, [0], 0])
637 self.assertEqual(str(d), '0')
638
639 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
640 self.assertEqual(str(d), '-4.34913534E-17')
641
642 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
643 self.assertEqual(str(d), '-4.34913534E-17')
644
645 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
646 self.assertEqual(str(d), '-4.34913534E-17')
647
Antoine Pitrou503ab332010-03-30 18:56:19 +0000648 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100649 Decimal = self.decimal.Decimal
650
Antoine Pitrou503ab332010-03-30 18:56:19 +0000651 self.assertIs(bool(Decimal(0)), False)
652 self.assertIs(bool(Decimal(1)), True)
653 self.assertEqual(Decimal(False), Decimal(0))
654 self.assertEqual(Decimal(True), Decimal(1))
655
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000656 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100657 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000658
659 #positive
660 d = Decimal(45)
661 e = Decimal(d)
662 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000663
664 #very large positive
665 d = Decimal(500000123)
666 e = Decimal(d)
667 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000668
669 #negative
670 d = Decimal(-45)
671 e = Decimal(d)
672 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000673
674 #zero
675 d = Decimal(0)
676 e = Decimal(d)
677 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000678
Raymond Hettinger96798592010-04-02 16:58:27 +0000679 @requires_IEEE_754
680 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100681
682 Decimal = self.decimal.Decimal
683
Raymond Hettinger96798592010-04-02 16:58:27 +0000684 r = Decimal(0.1)
685 self.assertEqual(type(r), Decimal)
686 self.assertEqual(str(r),
687 '0.1000000000000000055511151231257827021181583404541015625')
688 self.assertTrue(Decimal(float('nan')).is_qnan())
689 self.assertTrue(Decimal(float('inf')).is_infinite())
690 self.assertTrue(Decimal(float('-inf')).is_infinite())
691 self.assertEqual(str(Decimal(float('nan'))),
692 str(Decimal('NaN')))
693 self.assertEqual(str(Decimal(float('inf'))),
694 str(Decimal('Infinity')))
695 self.assertEqual(str(Decimal(float('-inf'))),
696 str(Decimal('-Infinity')))
697 self.assertEqual(str(Decimal(float('-0.0'))),
698 str(Decimal('-0')))
699 for i in range(200):
700 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
701 self.assertEqual(x, float(Decimal(x))) # roundtrip
702
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000703 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100704 Decimal = self.decimal.Decimal
705 InvalidOperation = self.decimal.InvalidOperation
706 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000707
Stefan Krah1919b7e2012-03-21 18:25:23 +0100708 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000709 nc.prec = 3
710
711 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000712 d = Decimal()
713 self.assertEqual(str(d), '0')
714 d = nc.create_decimal()
715 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000716
717 # from None
718 self.assertRaises(TypeError, nc.create_decimal, None)
719
720 # from int
721 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000722 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000723 self.assertEqual(nc.create_decimal(45678),
724 nc.create_decimal('457E+2'))
725
726 # from string
727 d = Decimal('456789')
728 self.assertEqual(str(d), '456789')
729 d = nc.create_decimal('456789')
730 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000731 # leading and trailing whitespace should result in a NaN;
732 # spaces are already checked in Cowlishaw's test-suite, so
733 # here we just check that a trailing newline results in a NaN
734 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000735
736 # from tuples
737 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
738 self.assertEqual(str(d), '-4.34913534E-17')
739 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
740 self.assertEqual(str(d), '-4.35E-17')
741
742 # from Decimal
743 prevdec = Decimal(500000123)
744 d = Decimal(prevdec)
745 self.assertEqual(str(d), '500000123')
746 d = nc.create_decimal(prevdec)
747 self.assertEqual(str(d), '5.00E+8')
748
Stefan Krah1919b7e2012-03-21 18:25:23 +0100749 # more integers
750 nc.prec = 28
751 nc.traps[InvalidOperation] = True
752
753 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
754 2**31-1, 2**31, 2**63-1, 2**63]:
755 d = nc.create_decimal(v)
756 self.assertTrue(isinstance(d, Decimal))
757 self.assertEqual(int(d), v)
758
759 nc.prec = 3
760 nc.traps[Rounded] = True
761 self.assertRaises(Rounded, nc.create_decimal, 1234)
762
763 # from string
764 nc.prec = 28
765 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
766 self.assertEqual(str(nc.create_decimal('45')), '45')
767 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
768 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
769
770 # invalid arguments
771 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
772 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
773 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
774
775 # too many NaN payload digits
776 nc.prec = 3
777 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
778 self.assertRaises(InvalidOperation, nc.create_decimal,
779 Decimal('NaN12345'))
780
781 nc.traps[InvalidOperation] = False
782 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
783 self.assertTrue(nc.flags[InvalidOperation])
784
785 nc.flags[InvalidOperation] = False
786 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
787 self.assertTrue(nc.flags[InvalidOperation])
788
789 def test_explicit_context_create_from_float(self):
790
791 Decimal = self.decimal.Decimal
792
793 nc = self.decimal.Context()
794 r = nc.create_decimal(0.1)
795 self.assertEqual(type(r), Decimal)
796 self.assertEqual(str(r), '0.1000000000000000055511151231')
797 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
798 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
799 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
800 self.assertEqual(str(nc.create_decimal(float('nan'))),
801 str(nc.create_decimal('NaN')))
802 self.assertEqual(str(nc.create_decimal(float('inf'))),
803 str(nc.create_decimal('Infinity')))
804 self.assertEqual(str(nc.create_decimal(float('-inf'))),
805 str(nc.create_decimal('-Infinity')))
806 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
807 str(nc.create_decimal('-0')))
808 nc.prec = 100
809 for i in range(200):
810 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
811 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
812
Mark Dickinson345adc42009-08-02 10:14:23 +0000813 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100814 Decimal = self.decimal.Decimal
815
Mark Dickinson345adc42009-08-02 10:14:23 +0000816 test_values = {
817 '\uff11': '1',
818 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
819 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
820 }
821 for input, expected in test_values.items():
822 self.assertEqual(str(Decimal(input)), expected)
823
Stefan Krah1919b7e2012-03-21 18:25:23 +0100824class CExplicitConstructionTest(ExplicitConstructionTest):
825 decimal = C
826class PyExplicitConstructionTest(ExplicitConstructionTest):
827 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000828
Stefan Krah1919b7e2012-03-21 18:25:23 +0100829class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000830 '''Unit tests for Implicit Construction cases of Decimal.'''
831
832 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100833 Decimal = self.decimal.Decimal
834 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000835
836 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100837 Decimal = self.decimal.Decimal
838
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000839 #normal
840 self.assertEqual(str(Decimal(5) + 45), '50')
841 #exceeding precision
842 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
843
844 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100845 Decimal = self.decimal.Decimal
846 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000847
848 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100849 Decimal = self.decimal.Decimal
850 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000851
852 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100853 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000854 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
855
Raymond Hettinger267b8682005-03-27 10:47:39 +0000856 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100857 Decimal = self.decimal.Decimal
858
Raymond Hettinger267b8682005-03-27 10:47:39 +0000859 # Allow other classes to be trained to interact with Decimals
860 class E:
861 def __divmod__(self, other):
862 return 'divmod ' + str(other)
863 def __rdivmod__(self, other):
864 return str(other) + ' rdivmod'
865 def __lt__(self, other):
866 return 'lt ' + str(other)
867 def __gt__(self, other):
868 return 'gt ' + str(other)
869 def __le__(self, other):
870 return 'le ' + str(other)
871 def __ge__(self, other):
872 return 'ge ' + str(other)
873 def __eq__(self, other):
874 return 'eq ' + str(other)
875 def __ne__(self, other):
876 return 'ne ' + str(other)
877
878 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
879 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
880 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
881 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
882 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
883 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
884 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
885 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
886
887 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000888 oplist = [
889 ('+', '__add__', '__radd__'),
890 ('-', '__sub__', '__rsub__'),
891 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000892 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000893 ('%', '__mod__', '__rmod__'),
894 ('//', '__floordiv__', '__rfloordiv__'),
895 ('**', '__pow__', '__rpow__')
896 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000897
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000898 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000899 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
900 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
901 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
902 'str' + lop + '10')
903 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
904 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000905
Stefan Krah1919b7e2012-03-21 18:25:23 +0100906class CImplicitConstructionTest(ImplicitConstructionTest):
907 decimal = C
908class PyImplicitConstructionTest(ImplicitConstructionTest):
909 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000910
Stefan Krah1919b7e2012-03-21 18:25:23 +0100911class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000912 '''Unit tests for the format function.'''
913 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100914 Decimal = self.decimal.Decimal
915
Christian Heimesf16baeb2008-02-29 14:57:44 +0000916 # triples giving a format, a Decimal, and the expected result
917 test_values = [
918 ('e', '0E-15', '0e-15'),
919 ('e', '2.3E-15', '2.3e-15'),
920 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
921 ('e', '2.30000E-15', '2.30000e-15'),
922 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
923 ('e', '1.5', '1.5e+0'),
924 ('e', '0.15', '1.5e-1'),
925 ('e', '0.015', '1.5e-2'),
926 ('e', '0.0000000000015', '1.5e-12'),
927 ('e', '15.0', '1.50e+1'),
928 ('e', '-15', '-1.5e+1'),
929 ('e', '0', '0e+0'),
930 ('e', '0E1', '0e+1'),
931 ('e', '0.0', '0e-1'),
932 ('e', '0.00', '0e-2'),
933 ('.6e', '0E-15', '0.000000e-9'),
934 ('.6e', '0', '0.000000e+6'),
935 ('.6e', '9.999999', '9.999999e+0'),
936 ('.6e', '9.9999999', '1.000000e+1'),
937 ('.6e', '-1.23e5', '-1.230000e+5'),
938 ('.6e', '1.23456789e-3', '1.234568e-3'),
939 ('f', '0', '0'),
940 ('f', '0.0', '0.0'),
941 ('f', '0E-2', '0.00'),
942 ('f', '0.00E-8', '0.0000000000'),
943 ('f', '0E1', '0'), # loses exponent information
944 ('f', '3.2E1', '32'),
945 ('f', '3.2E2', '320'),
946 ('f', '3.20E2', '320'),
947 ('f', '3.200E2', '320.0'),
948 ('f', '3.2E-6', '0.0000032'),
949 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
950 ('.6f', '0E1', '0.000000'),
951 ('.6f', '0', '0.000000'),
952 ('.0f', '0', '0'), # no decimal point
953 ('.0f', '0e-2', '0'),
954 ('.0f', '3.14159265', '3'),
955 ('.1f', '3.14159265', '3.1'),
956 ('.4f', '3.14159265', '3.1416'),
957 ('.6f', '3.14159265', '3.141593'),
958 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
959 ('.8f', '3.14159265', '3.14159265'),
960 ('.9f', '3.14159265', '3.141592650'),
961
962 ('g', '0', '0'),
963 ('g', '0.0', '0.0'),
964 ('g', '0E1', '0e+1'),
965 ('G', '0E1', '0E+1'),
966 ('g', '0E-5', '0.00000'),
967 ('g', '0E-6', '0.000000'),
968 ('g', '0E-7', '0e-7'),
969 ('g', '-0E2', '-0e+2'),
970 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100971 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000972 ('.1g', '3.14159265', '3'),
973 ('.2g', '3.14159265', '3.1'),
974 ('.5g', '3.14159265', '3.1416'),
975 ('.7g', '3.14159265', '3.141593'),
976 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
977 ('.9g', '3.14159265', '3.14159265'),
978 ('.10g', '3.14159265', '3.14159265'), # don't pad
979
980 ('%', '0E1', '0%'),
981 ('%', '0E0', '0%'),
982 ('%', '0E-1', '0%'),
983 ('%', '0E-2', '0%'),
984 ('%', '0E-3', '0.0%'),
985 ('%', '0E-4', '0.00%'),
986
987 ('.3%', '0', '0.000%'), # all zeros treated equally
988 ('.3%', '0E10', '0.000%'),
989 ('.3%', '0E-10', '0.000%'),
990 ('.3%', '2.34', '234.000%'),
991 ('.3%', '1.234567', '123.457%'),
992 ('.0%', '1.23', '123%'),
993
994 ('e', 'NaN', 'NaN'),
995 ('f', '-NaN123', '-NaN123'),
996 ('+g', 'NaN456', '+NaN456'),
997 ('.3e', 'Inf', 'Infinity'),
998 ('.16f', '-Inf', '-Infinity'),
999 ('.0g', '-sNaN', '-sNaN'),
1000
1001 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001002
Mark Dickinson79f52032009-03-17 23:12:51 +00001003 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001004 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001005 ('<6', '123', '123 '),
1006 ('>6', '123', ' 123'),
1007 ('^6', '123', ' 123 '),
1008 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001009 ('#<10', 'NaN', 'NaN#######'),
1010 ('#<10', '-4.3', '-4.3######'),
1011 ('#<+10', '0.0130', '+0.0130###'),
1012 ('#< 10', '0.0130', ' 0.0130###'),
1013 ('@>10', '-Inf', '@-Infinity'),
1014 ('#>5', '-Inf', '-Infinity'),
1015 ('?^5', '123', '?123?'),
1016 ('%^6', '123', '%123%%'),
1017 (' ^6', '-45.6', '-45.6 '),
1018 ('/=10', '-45.6', '-/////45.6'),
1019 ('/=+10', '45.6', '+/////45.6'),
1020 ('/= 10', '45.6', ' /////45.6'),
Stefan Krah6edda142013-05-29 15:45:38 +02001021 ('\x00=10', '-inf', '-\x00Infinity'),
1022 ('\x00^16', '-inf', '\x00\x00\x00-Infinity\x00\x00\x00\x00'),
1023 ('\x00>10', '1.2345', '\x00\x00\x00\x001.2345'),
1024 ('\x00<10', '1.2345', '1.2345\x00\x00\x00\x00'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001025
1026 # thousands separator
1027 (',', '1234567', '1,234,567'),
1028 (',', '123456', '123,456'),
1029 (',', '12345', '12,345'),
1030 (',', '1234', '1,234'),
1031 (',', '123', '123'),
1032 (',', '12', '12'),
1033 (',', '1', '1'),
1034 (',', '0', '0'),
1035 (',', '-1234567', '-1,234,567'),
1036 (',', '-123456', '-123,456'),
1037 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001038 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001039 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1040 ('+08,', '123456', '+123,456'), # but not if there's a sign
1041 (' 08,', '123456', ' 123,456'),
1042 ('08,', '-123456', '-123,456'),
1043 ('+09,', '123456', '+0,123,456'),
1044 # ... with fractional part...
1045 ('07,', '1234.56', '1,234.56'),
1046 ('08,', '1234.56', '1,234.56'),
1047 ('09,', '1234.56', '01,234.56'),
1048 ('010,', '1234.56', '001,234.56'),
1049 ('011,', '1234.56', '0,001,234.56'),
1050 ('012,', '1234.56', '0,001,234.56'),
1051 ('08,.1f', '1234.5', '01,234.5'),
1052 # no thousands separators in fraction part
1053 (',', '1.23456789', '1.23456789'),
1054 (',%', '123.456789', '12,345.6789%'),
1055 (',e', '123456', '1.23456e+5'),
1056 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001057
1058 # issue 6850
1059 ('a=-7.0', '0.12345', 'aaaa0.1'),
Stefan Krah298131a2014-08-26 20:46:49 +02001060
1061 # issue 22090
1062 ('<^+15.20%', 'inf', '<<+Infinity%<<<'),
1063 ('\x07>,%', 'sNaN1234567', 'sNaN1234567%'),
1064 ('=10.10%', 'NaN123', ' NaN123%'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001065 ]
1066 for fmt, d, result in test_values:
1067 self.assertEqual(format(Decimal(d), fmt), result)
1068
Stefan Krah1919b7e2012-03-21 18:25:23 +01001069 # bytes format argument
1070 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1071
Mark Dickinson79f52032009-03-17 23:12:51 +00001072 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001073 Decimal = self.decimal.Decimal
1074
Mark Dickinson79f52032009-03-17 23:12:51 +00001075 try:
1076 from locale import CHAR_MAX
1077 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06001078 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson79f52032009-03-17 23:12:51 +00001079
Stefan Krah1919b7e2012-03-21 18:25:23 +01001080 def make_grouping(lst):
1081 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1082
1083 def get_fmt(x, override=None, fmt='n'):
1084 if self.decimal == C:
1085 return Decimal(x).__format__(fmt, override)
1086 else:
1087 return Decimal(x).__format__(fmt, _localeconv=override)
1088
Mark Dickinson79f52032009-03-17 23:12:51 +00001089 # Set up some localeconv-like dictionaries
1090 en_US = {
1091 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001092 'grouping' : make_grouping([3, 3, 0]),
1093 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001094 }
1095
1096 fr_FR = {
1097 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001098 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001099 'thousands_sep' : ''
1100 }
1101
1102 ru_RU = {
1103 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001104 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001105 'thousands_sep' : ' '
1106 }
1107
1108 crazy = {
1109 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001110 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001111 'thousands_sep' : '-'
1112 }
1113
Stefan Krah1919b7e2012-03-21 18:25:23 +01001114 dotsep_wide = {
1115 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1116 'grouping': make_grouping([3, 3, 0]),
1117 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1118 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001119
1120 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1121 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1122 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1123 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1124
1125 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1126 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1127 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1128 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1129
1130 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1131 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1132 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1133 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1134
Mark Dickinson7303b592009-03-18 08:25:36 +00001135 # zero padding
1136 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1137 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1138 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1139 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1140
1141 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1142 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1143 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1144 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1145 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1146 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1147
1148 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1149 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1150 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1151 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1152 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1153 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1154 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1155 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1156
Stefan Krah1919b7e2012-03-21 18:25:23 +01001157 # wide char separator and decimal point
1158 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1159 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001160
Stefan Krah6fb204a2012-09-28 16:18:54 +02001161 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001162 def test_wide_char_separator_decimal_point(self):
1163 # locale with wide char separator and decimal point
Stefan Krah8a491a82012-09-28 17:17:11 +02001164 import locale
Stefan Krah1919b7e2012-03-21 18:25:23 +01001165 Decimal = self.decimal.Decimal
1166
Stefan Krah8a491a82012-09-28 17:17:11 +02001167 decimal_point = locale.localeconv()['decimal_point']
1168 thousands_sep = locale.localeconv()['thousands_sep']
Zachary Ware9fe6d862013-12-08 00:20:35 -06001169 if decimal_point != '\u066b':
1170 self.skipTest('inappropriate decimal point separator'
Zachary Ware0f533ac2013-12-12 10:32:16 -06001171 '({!a} not {!a})'.format(decimal_point, '\u066b'))
Zachary Ware9fe6d862013-12-08 00:20:35 -06001172 if thousands_sep != '\u066c':
1173 self.skipTest('inappropriate thousands separator'
Zachary Ware0f533ac2013-12-12 10:32:16 -06001174 '({!a} not {!a})'.format(thousands_sep, '\u066c'))
Stefan Krah8a491a82012-09-28 17:17:11 +02001175
Stefan Krah1919b7e2012-03-21 18:25:23 +01001176 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1177 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001178
1179class CFormatTest(FormatTest):
1180 decimal = C
1181class PyFormatTest(FormatTest):
1182 decimal = P
1183
1184class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001185 '''Unit tests for all arithmetic operators, binary and unary.'''
1186
1187 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001188 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001189
1190 d1 = Decimal('-11.1')
1191 d2 = Decimal('22.2')
1192
1193 #two Decimals
1194 self.assertEqual(d1+d2, Decimal('11.1'))
1195 self.assertEqual(d2+d1, Decimal('11.1'))
1196
1197 #with other type, left
1198 c = d1 + 5
1199 self.assertEqual(c, Decimal('-6.1'))
1200 self.assertEqual(type(c), type(d1))
1201
1202 #with other type, right
1203 c = 5 + d1
1204 self.assertEqual(c, Decimal('-6.1'))
1205 self.assertEqual(type(c), type(d1))
1206
1207 #inline with decimal
1208 d1 += d2
1209 self.assertEqual(d1, Decimal('11.1'))
1210
1211 #inline with other type
1212 d1 += 5
1213 self.assertEqual(d1, Decimal('16.1'))
1214
1215 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001216 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001217
1218 d1 = Decimal('-11.1')
1219 d2 = Decimal('22.2')
1220
1221 #two Decimals
1222 self.assertEqual(d1-d2, Decimal('-33.3'))
1223 self.assertEqual(d2-d1, Decimal('33.3'))
1224
1225 #with other type, left
1226 c = d1 - 5
1227 self.assertEqual(c, Decimal('-16.1'))
1228 self.assertEqual(type(c), type(d1))
1229
1230 #with other type, right
1231 c = 5 - d1
1232 self.assertEqual(c, Decimal('16.1'))
1233 self.assertEqual(type(c), type(d1))
1234
1235 #inline with decimal
1236 d1 -= d2
1237 self.assertEqual(d1, Decimal('-33.3'))
1238
1239 #inline with other type
1240 d1 -= 5
1241 self.assertEqual(d1, Decimal('-38.3'))
1242
1243 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001244 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001245
1246 d1 = Decimal('-5')
1247 d2 = Decimal('3')
1248
1249 #two Decimals
1250 self.assertEqual(d1*d2, Decimal('-15'))
1251 self.assertEqual(d2*d1, Decimal('-15'))
1252
1253 #with other type, left
1254 c = d1 * 5
1255 self.assertEqual(c, Decimal('-25'))
1256 self.assertEqual(type(c), type(d1))
1257
1258 #with other type, right
1259 c = 5 * d1
1260 self.assertEqual(c, Decimal('-25'))
1261 self.assertEqual(type(c), type(d1))
1262
1263 #inline with decimal
1264 d1 *= d2
1265 self.assertEqual(d1, Decimal('-15'))
1266
1267 #inline with other type
1268 d1 *= 5
1269 self.assertEqual(d1, Decimal('-75'))
1270
1271 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001272 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001273
1274 d1 = Decimal('-5')
1275 d2 = Decimal('2')
1276
1277 #two Decimals
1278 self.assertEqual(d1/d2, Decimal('-2.5'))
1279 self.assertEqual(d2/d1, Decimal('-0.4'))
1280
1281 #with other type, left
1282 c = d1 / 4
1283 self.assertEqual(c, Decimal('-1.25'))
1284 self.assertEqual(type(c), type(d1))
1285
1286 #with other type, right
1287 c = 4 / d1
1288 self.assertEqual(c, Decimal('-0.8'))
1289 self.assertEqual(type(c), type(d1))
1290
1291 #inline with decimal
1292 d1 /= d2
1293 self.assertEqual(d1, Decimal('-2.5'))
1294
1295 #inline with other type
1296 d1 /= 4
1297 self.assertEqual(d1, Decimal('-0.625'))
1298
1299 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001300 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001301
1302 d1 = Decimal('5')
1303 d2 = Decimal('2')
1304
1305 #two Decimals
1306 self.assertEqual(d1//d2, Decimal('2'))
1307 self.assertEqual(d2//d1, Decimal('0'))
1308
1309 #with other type, left
1310 c = d1 // 4
1311 self.assertEqual(c, Decimal('1'))
1312 self.assertEqual(type(c), type(d1))
1313
1314 #with other type, right
1315 c = 7 // d1
1316 self.assertEqual(c, Decimal('1'))
1317 self.assertEqual(type(c), type(d1))
1318
1319 #inline with decimal
1320 d1 //= d2
1321 self.assertEqual(d1, Decimal('2'))
1322
1323 #inline with other type
1324 d1 //= 2
1325 self.assertEqual(d1, Decimal('1'))
1326
1327 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001328 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001329
1330 d1 = Decimal('5')
1331 d2 = Decimal('2')
1332
1333 #two Decimals
1334 self.assertEqual(d1**d2, Decimal('25'))
1335 self.assertEqual(d2**d1, Decimal('32'))
1336
1337 #with other type, left
1338 c = d1 ** 4
1339 self.assertEqual(c, Decimal('625'))
1340 self.assertEqual(type(c), type(d1))
1341
1342 #with other type, right
1343 c = 7 ** d1
1344 self.assertEqual(c, Decimal('16807'))
1345 self.assertEqual(type(c), type(d1))
1346
1347 #inline with decimal
1348 d1 **= d2
1349 self.assertEqual(d1, Decimal('25'))
1350
1351 #inline with other type
1352 d1 **= 4
1353 self.assertEqual(d1, Decimal('390625'))
1354
1355 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001356 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001357
1358 d1 = Decimal('5')
1359 d2 = Decimal('2')
1360
1361 #two Decimals
1362 self.assertEqual(d1%d2, Decimal('1'))
1363 self.assertEqual(d2%d1, Decimal('2'))
1364
1365 #with other type, left
1366 c = d1 % 4
1367 self.assertEqual(c, Decimal('1'))
1368 self.assertEqual(type(c), type(d1))
1369
1370 #with other type, right
1371 c = 7 % d1
1372 self.assertEqual(c, Decimal('2'))
1373 self.assertEqual(type(c), type(d1))
1374
1375 #inline with decimal
1376 d1 %= d2
1377 self.assertEqual(d1, Decimal('1'))
1378
1379 #inline with other type
1380 d1 %= 4
1381 self.assertEqual(d1, Decimal('1'))
1382
1383 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001384 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001385
1386 d1 = Decimal('5')
1387 d2 = Decimal('2')
1388
1389 #two Decimals
1390 (p, q) = divmod(d1, d2)
1391 self.assertEqual(p, Decimal('2'))
1392 self.assertEqual(q, Decimal('1'))
1393 self.assertEqual(type(p), type(d1))
1394 self.assertEqual(type(q), type(d1))
1395
1396 #with other type, left
1397 (p, q) = divmod(d1, 4)
1398 self.assertEqual(p, Decimal('1'))
1399 self.assertEqual(q, Decimal('1'))
1400 self.assertEqual(type(p), type(d1))
1401 self.assertEqual(type(q), type(d1))
1402
1403 #with other type, right
1404 (p, q) = divmod(7, d1)
1405 self.assertEqual(p, Decimal('1'))
1406 self.assertEqual(q, Decimal('2'))
1407 self.assertEqual(type(p), type(d1))
1408 self.assertEqual(type(q), type(d1))
1409
1410 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001411 Decimal = self.decimal.Decimal
1412
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001413 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1414 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1415 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1416
Christian Heimes77c02eb2008-02-09 02:18:51 +00001417 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001418 # comparisons involving signaling nans signal InvalidOperation
1419
1420 # order comparisons (<, <=, >, >=) involving only quiet nans
1421 # also signal InvalidOperation
1422
1423 # equality comparisons (==, !=) involving only quiet nans
1424 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001425 Decimal = self.decimal.Decimal
1426 InvalidOperation = self.decimal.InvalidOperation
1427 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001428
Christian Heimes77c02eb2008-02-09 02:18:51 +00001429 n = Decimal('NaN')
1430 s = Decimal('sNaN')
1431 i = Decimal('Inf')
1432 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001433
1434 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1435 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1436 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1437 equality_ops = operator.eq, operator.ne
1438
1439 # results when InvalidOperation is not trapped
1440 for x, y in qnan_pairs + snan_pairs:
1441 for op in order_ops + equality_ops:
1442 got = op(x, y)
1443 expected = True if op is operator.ne else False
1444 self.assertIs(expected, got,
1445 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1446 "got {4!r}".format(
1447 expected, op.__name__, x, y, got))
1448
1449 # repeat the above, but this time trap the InvalidOperation
1450 with localcontext() as ctx:
1451 ctx.traps[InvalidOperation] = 1
1452
1453 for x, y in qnan_pairs:
1454 for op in equality_ops:
1455 got = op(x, y)
1456 expected = True if op is operator.ne else False
1457 self.assertIs(expected, got,
1458 "expected {0!r} for "
1459 "operator.{1}({2!r}, {3!r}); "
1460 "got {4!r}".format(
1461 expected, op.__name__, x, y, got))
1462
1463 for x, y in snan_pairs:
1464 for op in equality_ops:
1465 self.assertRaises(InvalidOperation, operator.eq, x, y)
1466 self.assertRaises(InvalidOperation, operator.ne, x, y)
1467
1468 for x, y in qnan_pairs + snan_pairs:
1469 for op in order_ops:
1470 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001471
Mark Dickinson84230a12010-02-18 14:49:50 +00001472 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001473 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001474
Stefan Krah1919b7e2012-03-21 18:25:23 +01001475 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001476 self.assertEqual(Decimal(1).copy_sign(-2), d)
1477 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1478
Stefan Krah1919b7e2012-03-21 18:25:23 +01001479class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1480 decimal = C
1481class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1482 decimal = P
1483
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001484# The following are two functions used to test threading in the next class
1485
1486def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001487 Decimal = cls.decimal.Decimal
1488 InvalidOperation = cls.decimal.InvalidOperation
1489 DivisionByZero = cls.decimal.DivisionByZero
1490 Overflow = cls.decimal.Overflow
1491 Underflow = cls.decimal.Underflow
1492 Inexact = cls.decimal.Inexact
1493 getcontext = cls.decimal.getcontext
1494 localcontext = cls.decimal.localcontext
1495
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001496 d1 = Decimal(1)
1497 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001498 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001499
Stefan Krah1919b7e2012-03-21 18:25:23 +01001500 cls.finish1.set()
1501 cls.synchro.wait()
1502
1503 test2 = d1/d3
1504 with localcontext() as c2:
1505 cls.assertTrue(c2.flags[Inexact])
1506 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1507 cls.assertTrue(c2.flags[DivisionByZero])
1508 with localcontext() as c3:
1509 cls.assertTrue(c3.flags[Inexact])
1510 cls.assertTrue(c3.flags[DivisionByZero])
1511 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1512 cls.assertTrue(c3.flags[InvalidOperation])
1513 del c3
1514 cls.assertFalse(c2.flags[InvalidOperation])
1515 del c2
1516
1517 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1518 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1519
1520 c1 = getcontext()
1521 cls.assertTrue(c1.flags[Inexact])
1522 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1523 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001524
1525def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001526 Decimal = cls.decimal.Decimal
1527 InvalidOperation = cls.decimal.InvalidOperation
1528 DivisionByZero = cls.decimal.DivisionByZero
1529 Overflow = cls.decimal.Overflow
1530 Underflow = cls.decimal.Underflow
1531 Inexact = cls.decimal.Inexact
1532 getcontext = cls.decimal.getcontext
1533 localcontext = cls.decimal.localcontext
1534
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001535 d1 = Decimal(1)
1536 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001537 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001538
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001539 thiscontext = getcontext()
1540 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001541 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001542
1543 with localcontext() as c2:
1544 cls.assertTrue(c2.flags[Inexact])
1545 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1546 cls.assertTrue(c2.flags[Overflow])
1547 with localcontext(thiscontext) as c3:
1548 cls.assertTrue(c3.flags[Inexact])
1549 cls.assertFalse(c3.flags[Overflow])
1550 c3.traps[Underflow] = True
1551 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1552 cls.assertTrue(c3.flags[Underflow])
1553 del c3
1554 cls.assertFalse(c2.flags[Underflow])
1555 cls.assertFalse(c2.traps[Underflow])
1556 del c2
1557
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001558 cls.synchro.set()
1559 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001560
Stefan Krah1919b7e2012-03-21 18:25:23 +01001561 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001562 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001563
1564 cls.assertFalse(thiscontext.traps[Underflow])
1565 cls.assertTrue(thiscontext.flags[Inexact])
1566 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1567 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001568
Stefan Krah1919b7e2012-03-21 18:25:23 +01001569class ThreadingTest(unittest.TestCase):
1570 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001571
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001572 # Take care executing this test from IDLE, there's an issue in threading
1573 # that hangs IDLE and I couldn't find it
1574
1575 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001576 DefaultContext = self.decimal.DefaultContext
1577
1578 if self.decimal == C and not self.decimal.HAVE_THREADS:
1579 self.skipTest("compiled without threading")
1580 # Test the "threading isolation" of a Context. Also test changing
1581 # the DefaultContext, which acts as a template for the thread-local
1582 # contexts.
1583 save_prec = DefaultContext.prec
1584 save_emax = DefaultContext.Emax
1585 save_emin = DefaultContext.Emin
1586 DefaultContext.prec = 24
1587 DefaultContext.Emax = 425000000
1588 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001589
1590 self.synchro = threading.Event()
1591 self.finish1 = threading.Event()
1592 self.finish2 = threading.Event()
1593
1594 th1 = threading.Thread(target=thfunc1, args=(self,))
1595 th2 = threading.Thread(target=thfunc2, args=(self,))
1596
1597 th1.start()
1598 th2.start()
1599
1600 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001601 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001602
1603 for sig in Signals[self.decimal]:
1604 self.assertFalse(DefaultContext.flags[sig])
1605
1606 DefaultContext.prec = save_prec
1607 DefaultContext.Emax = save_emax
1608 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001609
Stefan Krah1919b7e2012-03-21 18:25:23 +01001610@unittest.skipUnless(threading, 'threading required')
1611class CThreadingTest(ThreadingTest):
1612 decimal = C
1613@unittest.skipUnless(threading, 'threading required')
1614class PyThreadingTest(ThreadingTest):
1615 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001616
Stefan Krah1919b7e2012-03-21 18:25:23 +01001617class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001618 '''Unit tests for Usability cases of Decimal.'''
1619
1620 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001621
Stefan Krah1919b7e2012-03-21 18:25:23 +01001622 Decimal = self.decimal.Decimal
1623
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001624 da = Decimal('23.42')
1625 db = Decimal('23.42')
1626 dc = Decimal('45')
1627
1628 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001629 self.assertGreater(dc, da)
1630 self.assertGreaterEqual(dc, da)
1631 self.assertLess(da, dc)
1632 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001633 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001634 self.assertNotEqual(da, dc)
1635 self.assertLessEqual(da, db)
1636 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001637
1638 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001639 self.assertGreater(dc, 23)
1640 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001641 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001642
1643 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001644 self.assertNotEqual(da, 'ugly')
1645 self.assertNotEqual(da, 32.7)
1646 self.assertNotEqual(da, object())
1647 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001648
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001649 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001650 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001651 b = a[:]
1652 random.shuffle(a)
1653 a.sort()
1654 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001655
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001656 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001657 Decimal = self.decimal.Decimal
1658
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001659 da = Decimal('0.25')
1660 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001661 self.assertLess(da, 3.0)
1662 self.assertLessEqual(da, 3.0)
1663 self.assertGreater(db, 0.25)
1664 self.assertGreaterEqual(db, 0.25)
1665 self.assertNotEqual(da, 1.5)
1666 self.assertEqual(da, 0.25)
1667 self.assertGreater(3.0, da)
1668 self.assertGreaterEqual(3.0, da)
1669 self.assertLess(0.25, db)
1670 self.assertLessEqual(0.25, db)
1671 self.assertNotEqual(0.25, db)
1672 self.assertEqual(3.0, db)
1673 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001674
Stefan Krah1919b7e2012-03-21 18:25:23 +01001675 def test_decimal_complex_comparison(self):
1676 Decimal = self.decimal.Decimal
1677
1678 da = Decimal('0.25')
1679 db = Decimal('3.0')
1680 self.assertNotEqual(da, (1.5+0j))
1681 self.assertNotEqual((1.5+0j), da)
1682 self.assertEqual(da, (0.25+0j))
1683 self.assertEqual((0.25+0j), da)
1684 self.assertEqual((3.0+0j), db)
1685 self.assertEqual(db, (3.0+0j))
1686
1687 self.assertNotEqual(db, (3.0+1j))
1688 self.assertNotEqual((3.0+1j), db)
1689
1690 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1691 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1692 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1693 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1694
1695 def test_decimal_fraction_comparison(self):
1696 D = self.decimal.Decimal
1697 F = fractions[self.decimal].Fraction
1698 Context = self.decimal.Context
1699 localcontext = self.decimal.localcontext
1700 InvalidOperation = self.decimal.InvalidOperation
1701
1702
1703 emax = C.MAX_EMAX if C else 999999999
1704 emin = C.MIN_EMIN if C else -999999999
1705 etiny = C.MIN_ETINY if C else -1999999997
1706 c = Context(Emax=emax, Emin=emin)
1707
1708 with localcontext(c):
1709 c.prec = emax
1710 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1711 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1712 self.assertLess(F(0,1), D("1e" + str(etiny)))
1713 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1714 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1715 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1716
1717 self.assertEqual(D("0.1"), F(1,10))
1718 self.assertEqual(F(1,10), D("0.1"))
1719
1720 c.prec = 300
1721 self.assertNotEqual(D(1)/3, F(1,3))
1722 self.assertNotEqual(F(1,3), D(1)/3)
1723
1724 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1725 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1726
1727 self.assertGreater(D('inf'), F(99999999999,123))
1728 self.assertGreater(D('inf'), F(-99999999999,123))
1729 self.assertLess(D('-inf'), F(99999999999,123))
1730 self.assertLess(D('-inf'), F(-99999999999,123))
1731
1732 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1733 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1734 self.assertNotEqual(D('nan'), F(-9,123))
1735 self.assertNotEqual(F(-9,123), D('nan'))
1736
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001737 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001738 Decimal = self.decimal.Decimal
1739
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001740 d = Decimal('43.24')
1741 c = copy.copy(d)
1742 self.assertEqual(id(c), id(d))
1743 dc = copy.deepcopy(d)
1744 self.assertEqual(id(dc), id(d))
1745
1746 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001747
1748 Decimal = self.decimal.Decimal
1749 localcontext = self.decimal.localcontext
1750
Stefan Krahdc817b22010-11-17 11:16:34 +00001751 def hashit(d):
1752 a = hash(d)
1753 b = d.__hash__()
1754 self.assertEqual(a, b)
1755 return a
1756
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001757 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001758 hashit(Decimal(23))
1759 hashit(Decimal('Infinity'))
1760 hashit(Decimal('-Infinity'))
1761 hashit(Decimal('nan123'))
1762 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001763
1764 test_values = [Decimal(sign*(2**m + n))
1765 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001766 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001767 for n in range(-10, 10)
1768 for sign in [-1, 1]]
1769 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001770 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001771 Decimal("-0"), # zeros
1772 Decimal("0.00"),
1773 Decimal("-0.000"),
1774 Decimal("0E10"),
1775 Decimal("-0E12"),
1776 Decimal("10.0"), # negative exponent
1777 Decimal("-23.00000"),
1778 Decimal("1230E100"), # positive exponent
1779 Decimal("-4.5678E50"),
1780 # a value for which hash(n) != hash(n % (2**64-1))
1781 # in Python pre-2.6
1782 Decimal(2**64 + 2**32 - 1),
1783 # selection of values which fail with the old (before
1784 # version 2.6) long.__hash__
1785 Decimal("1.634E100"),
1786 Decimal("90.697E100"),
1787 Decimal("188.83E100"),
1788 Decimal("1652.9E100"),
1789 Decimal("56531E100"),
1790 ])
1791
1792 # check that hash(d) == hash(int(d)) for integral values
1793 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001794 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001795
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001796 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001797 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001798 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001799 self.assertTrue(hashit(Decimal('Inf')))
1800 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001801
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001802 # check that the hashes of a Decimal float match when they
1803 # represent exactly the same values
1804 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1805 '34.0', '2.5', '112390.625', '-0.515625']
1806 for s in test_strings:
1807 f = float(s)
1808 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001809 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001810
Stefan Krah1919b7e2012-03-21 18:25:23 +01001811 with localcontext() as c:
1812 # check that the value of the hash doesn't depend on the
1813 # current context (issue #1757)
1814 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001815
Stefan Krah1919b7e2012-03-21 18:25:23 +01001816 c.prec = 6
1817 h1 = hashit(x)
1818 c.prec = 10
1819 h2 = hashit(x)
1820 c.prec = 16
1821 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001822
Stefan Krah1919b7e2012-03-21 18:25:23 +01001823 self.assertEqual(h1, h2)
1824 self.assertEqual(h1, h3)
1825
1826 c.prec = 10000
1827 x = 1100 ** 1248
1828 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001829
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001830 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001831 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001832
1833 d1 = Decimal('15.32')
1834 d2 = Decimal('28.5')
1835 l1 = 15
1836 l2 = 28
1837
1838 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001839 self.assertIs(min(d1,d2), d1)
1840 self.assertIs(min(d2,d1), d1)
1841 self.assertIs(max(d1,d2), d2)
1842 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001843
Serhiy Storchaka95949422013-08-27 19:40:23 +03001844 #between Decimal and int
Ezio Melotti6607d512010-04-03 14:59:49 +00001845 self.assertIs(min(d1,l2), d1)
1846 self.assertIs(min(l2,d1), d1)
1847 self.assertIs(max(l1,d2), d2)
1848 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001849
1850 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001851 Decimal = self.decimal.Decimal
1852
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001853 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001854 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001855 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001856 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001857
1858 def test_tostring_methods(self):
1859 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001860 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001861
1862 d = Decimal('15.32')
1863 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001864 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001865
1866 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001867 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001868 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001869
1870 d1 = Decimal('66')
1871 d2 = Decimal('15.32')
1872
1873 #int
1874 self.assertEqual(int(d1), 66)
1875 self.assertEqual(int(d2), 15)
1876
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001877 #float
1878 self.assertEqual(float(d1), 66)
1879 self.assertEqual(float(d2), 15.32)
1880
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001881 #floor
1882 test_pairs = [
1883 ('123.00', 123),
1884 ('3.2', 3),
1885 ('3.54', 3),
1886 ('3.899', 3),
1887 ('-2.3', -3),
1888 ('-11.0', -11),
1889 ('0.0', 0),
1890 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001891 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001892 ]
1893 for d, i in test_pairs:
1894 self.assertEqual(math.floor(Decimal(d)), i)
1895 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1896 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1897 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1898 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1899 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1900
1901 #ceiling
1902 test_pairs = [
1903 ('123.00', 123),
1904 ('3.2', 4),
1905 ('3.54', 4),
1906 ('3.899', 4),
1907 ('-2.3', -2),
1908 ('-11.0', -11),
1909 ('0.0', 0),
1910 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001911 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001912 ]
1913 for d, i in test_pairs:
1914 self.assertEqual(math.ceil(Decimal(d)), i)
1915 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1916 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1917 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1918 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1919 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1920
1921 #round, single argument
1922 test_pairs = [
1923 ('123.00', 123),
1924 ('3.2', 3),
1925 ('3.54', 4),
1926 ('3.899', 4),
1927 ('-2.3', -2),
1928 ('-11.0', -11),
1929 ('0.0', 0),
1930 ('-0E3', 0),
1931 ('-3.5', -4),
1932 ('-2.5', -2),
1933 ('-1.5', -2),
1934 ('-0.5', 0),
1935 ('0.5', 0),
1936 ('1.5', 2),
1937 ('2.5', 2),
1938 ('3.5', 4),
1939 ]
1940 for d, i in test_pairs:
1941 self.assertEqual(round(Decimal(d)), i)
1942 self.assertRaises(ValueError, round, Decimal('-NaN'))
1943 self.assertRaises(ValueError, round, Decimal('sNaN'))
1944 self.assertRaises(ValueError, round, Decimal('NaN123'))
1945 self.assertRaises(OverflowError, round, Decimal('Inf'))
1946 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1947
1948 #round, two arguments; this is essentially equivalent
1949 #to quantize, which is already extensively tested
1950 test_triples = [
1951 ('123.456', -4, '0E+4'),
1952 ('123.456', -3, '0E+3'),
1953 ('123.456', -2, '1E+2'),
1954 ('123.456', -1, '1.2E+2'),
1955 ('123.456', 0, '123'),
1956 ('123.456', 1, '123.5'),
1957 ('123.456', 2, '123.46'),
1958 ('123.456', 3, '123.456'),
1959 ('123.456', 4, '123.4560'),
1960 ('123.455', 2, '123.46'),
1961 ('123.445', 2, '123.44'),
1962 ('Inf', 4, 'NaN'),
1963 ('-Inf', -23, 'NaN'),
1964 ('sNaN314', 3, 'NaN314'),
1965 ]
1966 for d, n, r in test_triples:
1967 self.assertEqual(str(round(Decimal(d), n)), r)
1968
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001969 def test_nan_to_float(self):
1970 # Test conversions of decimal NANs to float.
1971 # See http://bugs.python.org/issue15544
1972 Decimal = self.decimal.Decimal
1973 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1974 f = float(Decimal(s))
1975 self.assertTrue(math.isnan(f))
1976 sign = math.copysign(1.0, f)
1977 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1978
1979 def test_snan_to_float(self):
1980 Decimal = self.decimal.Decimal
1981 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1982 d = Decimal(s)
1983 self.assertRaises(ValueError, float, d)
1984
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001985 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001986 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001987
1988 #with zero
1989 d = Decimal( (0, (0,), 0) )
1990 self.assertEqual(d, eval(repr(d)))
1991
1992 #int
1993 d = Decimal( (1, (4, 5), 0) )
1994 self.assertEqual(d, eval(repr(d)))
1995
1996 #float
1997 d = Decimal( (0, (4, 5, 3, 4), -2) )
1998 self.assertEqual(d, eval(repr(d)))
1999
2000 #weird
2001 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2002 self.assertEqual(d, eval(repr(d)))
2003
2004 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002005 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002006
2007 #with zero
2008 d = Decimal(0)
2009 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
2010
2011 #int
2012 d = Decimal(-45)
2013 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2014
2015 #complicated string
2016 d = Decimal("-4.34913534E-17")
2017 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2018
Stefan Krah76e12172012-09-10 19:34:58 +02002019 # The '0' coefficient is implementation specific to decimal.py.
2020 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002021 d = Decimal("Infinity")
2022 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2023
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002024 #leading zeros in coefficient should be stripped
2025 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2026 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2027 d = Decimal( (1, (0, 0, 0), 37) )
2028 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2029 d = Decimal( (1, (), 37) )
2030 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2031
2032 #leading zeros in NaN diagnostic info should be stripped
2033 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2034 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2035 d = Decimal( (1, (0, 0, 0), 'N') )
2036 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2037 d = Decimal( (1, (), 'n') )
2038 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2039
Stefan Krah76e12172012-09-10 19:34:58 +02002040 # For infinities, decimal.py has always silently accepted any
2041 # coefficient tuple.
2042 d = Decimal( (0, (0,), 'F') )
2043 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2044 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2045 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2046 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2047 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002048
Stefan Krah1919b7e2012-03-21 18:25:23 +01002049 def test_subclassing(self):
2050 # Different behaviours when subclassing Decimal
2051 Decimal = self.decimal.Decimal
2052
2053 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002054 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002055
2056 d1 = MyDecimal(1)
2057 d2 = MyDecimal(2)
2058 d = d1 + d2
2059 self.assertIs(type(d), Decimal)
2060
2061 d = d1.max(d2)
2062 self.assertIs(type(d), Decimal)
2063
2064 d = copy.copy(d1)
2065 self.assertIs(type(d), MyDecimal)
2066 self.assertEqual(d, d1)
2067
2068 d = copy.deepcopy(d1)
2069 self.assertIs(type(d), MyDecimal)
2070 self.assertEqual(d, d1)
2071
Stefan Krah0f82b762012-11-08 11:17:29 +01002072 # Decimal(Decimal)
2073 d = Decimal('1.0')
2074 x = Decimal(d)
2075 self.assertIs(type(x), Decimal)
2076 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002077
Stefan Krah0f82b762012-11-08 11:17:29 +01002078 # MyDecimal(Decimal)
2079 m = MyDecimal(d)
2080 self.assertIs(type(m), MyDecimal)
2081 self.assertEqual(m, d)
2082 self.assertIs(m.y, None)
2083
2084 # Decimal(MyDecimal)
2085 x = Decimal(m)
2086 self.assertIs(type(x), Decimal)
2087 self.assertEqual(x, d)
2088
2089 # MyDecimal(MyDecimal)
2090 m.y = 9
2091 x = MyDecimal(m)
2092 self.assertIs(type(x), MyDecimal)
2093 self.assertEqual(x, d)
2094 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002095
Stefan Krah1919b7e2012-03-21 18:25:23 +01002096 def test_implicit_context(self):
2097 Decimal = self.decimal.Decimal
2098 getcontext = self.decimal.getcontext
2099
2100 # Check results when context given implicitly. (Issue 2478)
2101 c = getcontext()
2102 self.assertEqual(str(Decimal(0).sqrt()),
2103 str(c.sqrt(Decimal(0))))
2104
Stefan Krah040e3112012-12-15 22:33:33 +01002105 def test_none_args(self):
2106 Decimal = self.decimal.Decimal
2107 Context = self.decimal.Context
2108 localcontext = self.decimal.localcontext
2109 InvalidOperation = self.decimal.InvalidOperation
2110 DivisionByZero = self.decimal.DivisionByZero
2111 Overflow = self.decimal.Overflow
2112 Underflow = self.decimal.Underflow
2113 Subnormal = self.decimal.Subnormal
2114 Inexact = self.decimal.Inexact
2115 Rounded = self.decimal.Rounded
2116 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002117
2118 with localcontext(Context()) as c:
2119 c.prec = 7
2120 c.Emax = 999
2121 c.Emin = -999
2122
2123 x = Decimal("111")
2124 y = Decimal("1e9999")
2125 z = Decimal("1e-9999")
2126
2127 ##### Unary functions
2128 c.clear_flags()
2129 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2130 self.assertTrue(c.flags[Inexact])
2131 self.assertTrue(c.flags[Rounded])
2132 c.clear_flags()
2133 self.assertRaises(Overflow, y.exp, context=None)
2134 self.assertTrue(c.flags[Overflow])
2135
2136 self.assertIs(z.is_normal(context=None), False)
2137 self.assertIs(z.is_subnormal(context=None), True)
2138
2139 c.clear_flags()
2140 self.assertEqual(str(x.ln(context=None)), '4.709530')
2141 self.assertTrue(c.flags[Inexact])
2142 self.assertTrue(c.flags[Rounded])
2143 c.clear_flags()
2144 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2145 self.assertTrue(c.flags[InvalidOperation])
2146
2147 c.clear_flags()
2148 self.assertEqual(str(x.log10(context=None)), '2.045323')
2149 self.assertTrue(c.flags[Inexact])
2150 self.assertTrue(c.flags[Rounded])
2151 c.clear_flags()
2152 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2153 self.assertTrue(c.flags[InvalidOperation])
2154
2155 c.clear_flags()
2156 self.assertEqual(str(x.logb(context=None)), '2')
2157 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2158 self.assertTrue(c.flags[DivisionByZero])
2159
2160 c.clear_flags()
2161 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2162 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2163 self.assertTrue(c.flags[InvalidOperation])
2164
2165 c.clear_flags()
2166 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2167 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2168 self.assertTrue(c.flags[InvalidOperation])
2169
2170 c.clear_flags()
2171 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2172 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2173 self.assertTrue(c.flags[InvalidOperation])
2174
2175 c.clear_flags()
2176 self.assertEqual(str(z.normalize(context=None)), '0')
2177 self.assertRaises(Overflow, y.normalize, context=None)
2178 self.assertTrue(c.flags[Overflow])
2179
2180 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2181
2182 c.clear_flags()
2183 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2184 self.assertTrue(c.flags[Clamped])
2185 self.assertTrue(c.flags[Inexact])
2186 self.assertTrue(c.flags[Rounded])
2187 self.assertTrue(c.flags[Subnormal])
2188 self.assertTrue(c.flags[Underflow])
2189 c.clear_flags()
2190 self.assertRaises(Overflow, y.sqrt, context=None)
2191 self.assertTrue(c.flags[Overflow])
2192
2193 c.capitals = 0
2194 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2195 c.capitals = 1
2196
2197
2198 ##### Binary functions
2199 c.clear_flags()
2200 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2201 self.assertEqual(ans, 'NaN1287828')
2202 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2203 self.assertTrue(c.flags[InvalidOperation])
2204
2205 c.clear_flags()
2206 ans = str(x.compare_signal(8224, context=None))
2207 self.assertEqual(ans, '-1')
2208 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2209 self.assertTrue(c.flags[InvalidOperation])
2210
2211 c.clear_flags()
2212 ans = str(x.logical_and(101, context=None))
2213 self.assertEqual(ans, '101')
2214 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2215 self.assertTrue(c.flags[InvalidOperation])
2216
2217 c.clear_flags()
2218 ans = str(x.logical_or(101, context=None))
2219 self.assertEqual(ans, '111')
2220 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2221 self.assertTrue(c.flags[InvalidOperation])
2222
2223 c.clear_flags()
2224 ans = str(x.logical_xor(101, context=None))
2225 self.assertEqual(ans, '10')
2226 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2227 self.assertTrue(c.flags[InvalidOperation])
2228
2229 c.clear_flags()
2230 ans = str(x.max(101, context=None))
2231 self.assertEqual(ans, '111')
2232 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2233 self.assertTrue(c.flags[InvalidOperation])
2234
2235 c.clear_flags()
2236 ans = str(x.max_mag(101, context=None))
2237 self.assertEqual(ans, '111')
2238 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2239 self.assertTrue(c.flags[InvalidOperation])
2240
2241 c.clear_flags()
2242 ans = str(x.min(101, context=None))
2243 self.assertEqual(ans, '101')
2244 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2245 self.assertTrue(c.flags[InvalidOperation])
2246
2247 c.clear_flags()
2248 ans = str(x.min_mag(101, context=None))
2249 self.assertEqual(ans, '101')
2250 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2251 self.assertTrue(c.flags[InvalidOperation])
2252
2253 c.clear_flags()
2254 ans = str(x.remainder_near(101, context=None))
2255 self.assertEqual(ans, '10')
2256 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2257 self.assertTrue(c.flags[InvalidOperation])
2258
2259 c.clear_flags()
2260 ans = str(x.rotate(2, context=None))
2261 self.assertEqual(ans, '11100')
2262 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2263 self.assertTrue(c.flags[InvalidOperation])
2264
2265 c.clear_flags()
2266 ans = str(x.scaleb(7, context=None))
2267 self.assertEqual(ans, '1.11E+9')
2268 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2269 self.assertTrue(c.flags[InvalidOperation])
2270
2271 c.clear_flags()
2272 ans = str(x.shift(2, context=None))
2273 self.assertEqual(ans, '11100')
2274 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2275 self.assertTrue(c.flags[InvalidOperation])
2276
2277
2278 ##### Ternary functions
2279 c.clear_flags()
2280 ans = str(x.fma(2, 3, context=None))
2281 self.assertEqual(ans, '225')
2282 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2283 self.assertTrue(c.flags[Overflow])
2284
2285
2286 ##### Special cases
2287 c.rounding = ROUND_HALF_EVEN
2288 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2289 self.assertEqual(ans, '2')
2290 c.rounding = ROUND_DOWN
2291 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2292 self.assertEqual(ans, '1')
2293 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2294 self.assertEqual(ans, '2')
2295 c.clear_flags()
2296 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2297 self.assertTrue(c.flags[InvalidOperation])
2298
2299 c.rounding = ROUND_HALF_EVEN
2300 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2301 self.assertEqual(ans, '2')
2302 c.rounding = ROUND_DOWN
2303 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2304 self.assertEqual(ans, '1')
2305 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2306 self.assertEqual(ans, '2')
2307 c.clear_flags()
2308 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2309 self.assertTrue(c.flags[InvalidOperation])
2310
2311 c.rounding = ROUND_HALF_EVEN
2312 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2313 self.assertEqual(ans, '2')
2314 c.rounding = ROUND_DOWN
2315 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2316 self.assertEqual(ans, '1')
2317 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2318 self.assertEqual(ans, '2')
2319 c.clear_flags()
2320 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2321 self.assertTrue(c.flags[InvalidOperation])
2322
2323 c.rounding = ROUND_UP
2324 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2325 self.assertEqual(ans, '1.501')
2326 c.rounding = ROUND_DOWN
2327 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2328 self.assertEqual(ans, '1.500')
2329 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2330 self.assertEqual(ans, '1.501')
2331 c.clear_flags()
2332 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2333 self.assertTrue(c.flags[InvalidOperation])
2334
2335 with localcontext(Context()) as context:
2336 context.prec = 7
2337 context.Emax = 999
2338 context.Emin = -999
2339 with localcontext(ctx=None) as c:
2340 self.assertEqual(c.prec, 7)
2341 self.assertEqual(c.Emax, 999)
2342 self.assertEqual(c.Emin, -999)
2343
Stefan Krah1919b7e2012-03-21 18:25:23 +01002344 def test_conversions_from_int(self):
2345 # Check that methods taking a second Decimal argument will
2346 # always accept an integer in place of a Decimal.
2347 Decimal = self.decimal.Decimal
2348
2349 self.assertEqual(Decimal(4).compare(3),
2350 Decimal(4).compare(Decimal(3)))
2351 self.assertEqual(Decimal(4).compare_signal(3),
2352 Decimal(4).compare_signal(Decimal(3)))
2353 self.assertEqual(Decimal(4).compare_total(3),
2354 Decimal(4).compare_total(Decimal(3)))
2355 self.assertEqual(Decimal(4).compare_total_mag(3),
2356 Decimal(4).compare_total_mag(Decimal(3)))
2357 self.assertEqual(Decimal(10101).logical_and(1001),
2358 Decimal(10101).logical_and(Decimal(1001)))
2359 self.assertEqual(Decimal(10101).logical_or(1001),
2360 Decimal(10101).logical_or(Decimal(1001)))
2361 self.assertEqual(Decimal(10101).logical_xor(1001),
2362 Decimal(10101).logical_xor(Decimal(1001)))
2363 self.assertEqual(Decimal(567).max(123),
2364 Decimal(567).max(Decimal(123)))
2365 self.assertEqual(Decimal(567).max_mag(123),
2366 Decimal(567).max_mag(Decimal(123)))
2367 self.assertEqual(Decimal(567).min(123),
2368 Decimal(567).min(Decimal(123)))
2369 self.assertEqual(Decimal(567).min_mag(123),
2370 Decimal(567).min_mag(Decimal(123)))
2371 self.assertEqual(Decimal(567).next_toward(123),
2372 Decimal(567).next_toward(Decimal(123)))
2373 self.assertEqual(Decimal(1234).quantize(100),
2374 Decimal(1234).quantize(Decimal(100)))
2375 self.assertEqual(Decimal(768).remainder_near(1234),
2376 Decimal(768).remainder_near(Decimal(1234)))
2377 self.assertEqual(Decimal(123).rotate(1),
2378 Decimal(123).rotate(Decimal(1)))
2379 self.assertEqual(Decimal(1234).same_quantum(1000),
2380 Decimal(1234).same_quantum(Decimal(1000)))
2381 self.assertEqual(Decimal('9.123').scaleb(-100),
2382 Decimal('9.123').scaleb(Decimal(-100)))
2383 self.assertEqual(Decimal(456).shift(-1),
2384 Decimal(456).shift(Decimal(-1)))
2385
2386 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2387 Decimal(-12).fma(Decimal(45), Decimal(67)))
2388 self.assertEqual(Decimal(-12).fma(45, 67),
2389 Decimal(-12).fma(Decimal(45), Decimal(67)))
2390 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2391 Decimal(-12).fma(Decimal(45), Decimal(67)))
2392
2393class CUsabilityTest(UsabilityTest):
2394 decimal = C
2395class PyUsabilityTest(UsabilityTest):
2396 decimal = P
2397
2398class PythonAPItests(unittest.TestCase):
2399
2400 def test_abc(self):
2401 Decimal = self.decimal.Decimal
2402
2403 self.assertTrue(issubclass(Decimal, numbers.Number))
2404 self.assertFalse(issubclass(Decimal, numbers.Real))
2405 self.assertIsInstance(Decimal(0), numbers.Number)
2406 self.assertNotIsInstance(Decimal(0), numbers.Real)
2407
2408 def test_pickle(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +02002409 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2410 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002411
Serhiy Storchakabad12572014-12-15 14:03:42 +02002412 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002413
Serhiy Storchakabad12572014-12-15 14:03:42 +02002414 # Round trip
2415 sys.modules['decimal'] = self.decimal
2416 d = Decimal('-3.141590000')
2417 p = pickle.dumps(d, proto)
2418 e = pickle.loads(p)
2419 self.assertEqual(d, e)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002420
Serhiy Storchakabad12572014-12-15 14:03:42 +02002421 if C:
2422 # Test interchangeability
2423 x = C.Decimal('-3.123e81723')
2424 y = P.Decimal('-3.123e81723')
Stefan Krah1919b7e2012-03-21 18:25:23 +01002425
Serhiy Storchakabad12572014-12-15 14:03:42 +02002426 sys.modules['decimal'] = C
2427 sx = pickle.dumps(x, proto)
2428 sys.modules['decimal'] = P
2429 r = pickle.loads(sx)
2430 self.assertIsInstance(r, P.Decimal)
2431 self.assertEqual(r, y)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002432
Serhiy Storchakabad12572014-12-15 14:03:42 +02002433 sys.modules['decimal'] = P
2434 sy = pickle.dumps(y, proto)
2435 sys.modules['decimal'] = C
2436 r = pickle.loads(sy)
2437 self.assertIsInstance(r, C.Decimal)
2438 self.assertEqual(r, x)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002439
Serhiy Storchakabad12572014-12-15 14:03:42 +02002440 x = C.Decimal('-3.123e81723').as_tuple()
2441 y = P.Decimal('-3.123e81723').as_tuple()
Stefan Krah8fb74a32014-04-29 18:24:50 +02002442
Serhiy Storchakabad12572014-12-15 14:03:42 +02002443 sys.modules['decimal'] = C
2444 sx = pickle.dumps(x, proto)
2445 sys.modules['decimal'] = P
2446 r = pickle.loads(sx)
2447 self.assertIsInstance(r, P.DecimalTuple)
2448 self.assertEqual(r, y)
Stefan Krah8fb74a32014-04-29 18:24:50 +02002449
Serhiy Storchakabad12572014-12-15 14:03:42 +02002450 sys.modules['decimal'] = P
2451 sy = pickle.dumps(y, proto)
2452 sys.modules['decimal'] = C
2453 r = pickle.loads(sy)
2454 self.assertIsInstance(r, C.DecimalTuple)
2455 self.assertEqual(r, x)
Stefan Krah8fb74a32014-04-29 18:24:50 +02002456
Serhiy Storchakabad12572014-12-15 14:03:42 +02002457 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002458
2459 def test_int(self):
2460 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002461
2462 for x in range(-250, 250):
2463 s = '%0.2f' % (x / 100.0)
2464 # should work the same as for floats
2465 self.assertEqual(int(Decimal(s)), int(float(s)))
2466 # should work the same as to_integral in the ROUND_DOWN mode
2467 d = Decimal(s)
2468 r = d.to_integral(ROUND_DOWN)
2469 self.assertEqual(Decimal(int(d)), r)
2470
2471 self.assertRaises(ValueError, int, Decimal('-nan'))
2472 self.assertRaises(ValueError, int, Decimal('snan'))
2473 self.assertRaises(OverflowError, int, Decimal('inf'))
2474 self.assertRaises(OverflowError, int, Decimal('-inf'))
2475
2476 def test_trunc(self):
2477 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002478
2479 for x in range(-250, 250):
2480 s = '%0.2f' % (x / 100.0)
2481 # should work the same as for floats
2482 self.assertEqual(int(Decimal(s)), int(float(s)))
2483 # should work the same as to_integral in the ROUND_DOWN mode
2484 d = Decimal(s)
2485 r = d.to_integral(ROUND_DOWN)
2486 self.assertEqual(Decimal(math.trunc(d)), r)
2487
2488 def test_from_float(self):
2489
2490 Decimal = self.decimal.Decimal
2491
2492 class MyDecimal(Decimal):
2493 pass
2494
2495 self.assertTrue(issubclass(MyDecimal, Decimal))
2496
2497 r = MyDecimal.from_float(0.1)
2498 self.assertEqual(type(r), MyDecimal)
2499 self.assertEqual(str(r),
2500 '0.1000000000000000055511151231257827021181583404541015625')
2501 bigint = 12345678901234567890123456789
2502 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2503 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2504 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2505 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2506 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2507 str(Decimal('NaN')))
2508 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2509 str(Decimal('Infinity')))
2510 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2511 str(Decimal('-Infinity')))
2512 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2513 for i in range(200):
2514 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2515 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2516
2517 def test_create_decimal_from_float(self):
2518 Decimal = self.decimal.Decimal
2519 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002520 Inexact = self.decimal.Inexact
2521
2522 context = Context(prec=5, rounding=ROUND_DOWN)
2523 self.assertEqual(
2524 context.create_decimal_from_float(math.pi),
2525 Decimal('3.1415')
2526 )
2527 context = Context(prec=5, rounding=ROUND_UP)
2528 self.assertEqual(
2529 context.create_decimal_from_float(math.pi),
2530 Decimal('3.1416')
2531 )
2532 context = Context(prec=5, traps=[Inexact])
2533 self.assertRaises(
2534 Inexact,
2535 context.create_decimal_from_float,
2536 math.pi
2537 )
2538 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2539 "Decimal('-0')")
2540 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2541 "Decimal('1')")
2542 self.assertEqual(repr(context.create_decimal_from_float(10)),
2543 "Decimal('10')")
2544
2545 def test_quantize(self):
2546 Decimal = self.decimal.Decimal
2547 Context = self.decimal.Context
2548 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002549
2550 c = Context(Emax=99999, Emin=-99999)
2551 self.assertEqual(
2552 Decimal('7.335').quantize(Decimal('.01')),
2553 Decimal('7.34')
2554 )
2555 self.assertEqual(
2556 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2557 Decimal('7.33')
2558 )
2559 self.assertRaises(
2560 InvalidOperation,
2561 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2562 )
2563
2564 c = Context()
2565 d = Decimal("0.871831e800")
2566 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2567 self.assertEqual(x, Decimal('8.71E+799'))
2568
2569 def test_complex(self):
2570 Decimal = self.decimal.Decimal
2571
2572 x = Decimal("9.8182731e181273")
2573 self.assertEqual(x.real, x)
2574 self.assertEqual(x.imag, 0)
2575 self.assertEqual(x.conjugate(), x)
2576
2577 x = Decimal("1")
2578 self.assertEqual(complex(x), complex(float(1)))
2579
2580 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2581 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2582 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2583 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2584
2585 def test_named_parameters(self):
2586 D = self.decimal.Decimal
2587 Context = self.decimal.Context
2588 localcontext = self.decimal.localcontext
2589 InvalidOperation = self.decimal.InvalidOperation
2590 Overflow = self.decimal.Overflow
2591
2592 xc = Context()
2593 xc.prec = 1
2594 xc.Emax = 1
2595 xc.Emin = -1
2596
2597 with localcontext() as c:
2598 c.clear_flags()
2599
2600 self.assertEqual(D(9, xc), 9)
2601 self.assertEqual(D(9, context=xc), 9)
2602 self.assertEqual(D(context=xc, value=9), 9)
2603 self.assertEqual(D(context=xc), 0)
2604 xc.clear_flags()
2605 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2606 self.assertTrue(xc.flags[InvalidOperation])
2607 self.assertFalse(c.flags[InvalidOperation])
2608
2609 xc.clear_flags()
2610 self.assertEqual(D(2).exp(context=xc), 7)
2611 self.assertRaises(Overflow, D(8).exp, context=xc)
2612 self.assertTrue(xc.flags[Overflow])
2613 self.assertFalse(c.flags[Overflow])
2614
2615 xc.clear_flags()
2616 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2617 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2618 self.assertTrue(xc.flags[InvalidOperation])
2619 self.assertFalse(c.flags[InvalidOperation])
2620
2621 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2622 self.assertEqual(D(-1).next_minus(context=xc), -2)
2623 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2624 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2625 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2626 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2627 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2628 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2629
2630 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2631 xc.clear_flags()
2632 self.assertRaises(InvalidOperation,
2633 D("0").compare_signal, D('nan'), context=xc)
2634 self.assertTrue(xc.flags[InvalidOperation])
2635 self.assertFalse(c.flags[InvalidOperation])
2636 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2637 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2638 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2639 D('-0.3'))
2640 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2641 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2642 D('0.0'))
2643 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2644 xc.clear_flags()
2645 self.assertRaises(InvalidOperation,
2646 D("0.2").quantize, D('1e10'), context=xc)
2647 self.assertTrue(xc.flags[InvalidOperation])
2648 self.assertFalse(c.flags[InvalidOperation])
2649 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2650 D('-0.5'))
2651
2652 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2653 D('7E+1'))
2654
2655 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2656 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2657 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2658 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2659 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2660 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2661 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2662 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2663
2664 self.assertFalse(D("0.01").is_normal(context=xc))
2665 self.assertTrue(D("0.01").is_subnormal(context=xc))
2666
2667 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2668 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2669 self.assertRaises(TypeError, D(1).radix, context=xc)
2670
2671 self.assertEqual(D(-111).logb(context=xc), 2)
2672 self.assertEqual(D(0).logical_invert(context=xc), 1)
2673 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2674 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2675
2676 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2677 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2678 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2679 self.assertEqual(D('23').rotate(1, context=xc), 3)
2680 self.assertEqual(D('23').rotate(1, context=xc), 3)
2681 xc.clear_flags()
2682 self.assertRaises(Overflow,
2683 D('23').scaleb, 1, context=xc)
2684 self.assertTrue(xc.flags[Overflow])
2685 self.assertFalse(c.flags[Overflow])
2686 self.assertEqual(D('23').shift(-1, context=xc), 0)
2687
2688 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2689 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2690
Stefan Krah040e3112012-12-15 22:33:33 +01002691 self.assertEqual(D(1).canonical(), 1)
2692 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2693 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2694 self.assertRaises(TypeError, D(1).canonical, context="x")
2695 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002696
Stefan Krahb6405ef2012-03-23 14:46:48 +01002697 def test_exception_hierarchy(self):
2698
2699 decimal = self.decimal
2700 DecimalException = decimal.DecimalException
2701 InvalidOperation = decimal.InvalidOperation
2702 FloatOperation = decimal.FloatOperation
2703 DivisionByZero = decimal.DivisionByZero
2704 Overflow = decimal.Overflow
2705 Underflow = decimal.Underflow
2706 Subnormal = decimal.Subnormal
2707 Inexact = decimal.Inexact
2708 Rounded = decimal.Rounded
2709 Clamped = decimal.Clamped
2710
2711 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2712
2713 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2714 self.assertTrue(issubclass(FloatOperation, DecimalException))
2715 self.assertTrue(issubclass(FloatOperation, TypeError))
2716 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2717 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2718 self.assertTrue(issubclass(Overflow, Rounded))
2719 self.assertTrue(issubclass(Overflow, Inexact))
2720 self.assertTrue(issubclass(Overflow, DecimalException))
2721 self.assertTrue(issubclass(Underflow, Inexact))
2722 self.assertTrue(issubclass(Underflow, Rounded))
2723 self.assertTrue(issubclass(Underflow, Subnormal))
2724 self.assertTrue(issubclass(Underflow, DecimalException))
2725
2726 self.assertTrue(issubclass(Subnormal, DecimalException))
2727 self.assertTrue(issubclass(Inexact, DecimalException))
2728 self.assertTrue(issubclass(Rounded, DecimalException))
2729 self.assertTrue(issubclass(Clamped, DecimalException))
2730
2731 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2732 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2733 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2734 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2735 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2736
Stefan Krah1919b7e2012-03-21 18:25:23 +01002737class CPythonAPItests(PythonAPItests):
2738 decimal = C
2739class PyPythonAPItests(PythonAPItests):
2740 decimal = P
2741
2742class ContextAPItests(unittest.TestCase):
2743
Stefan Krah9a4ff432012-12-16 21:10:35 +01002744 def test_none_args(self):
2745 Context = self.decimal.Context
2746 InvalidOperation = self.decimal.InvalidOperation
2747 DivisionByZero = self.decimal.DivisionByZero
2748 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002749
2750 c1 = Context()
2751 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2752 capitals=None, clamp=None, flags=None, traps=None)
2753 for c in [c1, c2]:
2754 self.assertEqual(c.prec, 28)
2755 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2756 self.assertEqual(c.Emax, 999999)
2757 self.assertEqual(c.Emin, -999999)
2758 self.assertEqual(c.capitals, 1)
2759 self.assertEqual(c.clamp, 0)
2760 assert_signals(self, c, 'flags', [])
2761 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2762 Overflow])
2763
Stefan Krah59a4a932013-01-16 12:58:59 +01002764 @cpython_only
2765 def test_from_legacy_strings(self):
2766 import _testcapi
2767 c = self.decimal.Context()
2768
2769 for rnd in RoundingModes:
2770 c.rounding = _testcapi.unicode_legacy_string(rnd)
2771 self.assertEqual(c.rounding, rnd)
2772
2773 s = _testcapi.unicode_legacy_string('')
2774 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2775
2776 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2777 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2778
Stefan Krah1919b7e2012-03-21 18:25:23 +01002779 def test_pickle(self):
2780
Serhiy Storchakabad12572014-12-15 14:03:42 +02002781 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2782 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002783
Serhiy Storchakabad12572014-12-15 14:03:42 +02002784 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002785
Serhiy Storchakabad12572014-12-15 14:03:42 +02002786 # Round trip
2787 sys.modules['decimal'] = self.decimal
2788 c = Context()
2789 e = pickle.loads(pickle.dumps(c, proto))
Stefan Krah1919b7e2012-03-21 18:25:23 +01002790
Serhiy Storchakabad12572014-12-15 14:03:42 +02002791 self.assertEqual(c.prec, e.prec)
2792 self.assertEqual(c.Emin, e.Emin)
2793 self.assertEqual(c.Emax, e.Emax)
2794 self.assertEqual(c.rounding, e.rounding)
2795 self.assertEqual(c.capitals, e.capitals)
2796 self.assertEqual(c.clamp, e.clamp)
2797 self.assertEqual(c.flags, e.flags)
2798 self.assertEqual(c.traps, e.traps)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002799
Serhiy Storchakabad12572014-12-15 14:03:42 +02002800 # Test interchangeability
2801 combinations = [(C, P), (P, C)] if C else [(P, P)]
2802 for dumper, loader in combinations:
2803 for ri, _ in enumerate(RoundingModes):
2804 for fi, _ in enumerate(OrderedSignals[dumper]):
2805 for ti, _ in enumerate(OrderedSignals[dumper]):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002806
Serhiy Storchakabad12572014-12-15 14:03:42 +02002807 prec = random.randrange(1, 100)
2808 emin = random.randrange(-100, 0)
2809 emax = random.randrange(1, 100)
2810 caps = random.randrange(2)
2811 clamp = random.randrange(2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002812
Serhiy Storchakabad12572014-12-15 14:03:42 +02002813 # One module dumps
2814 sys.modules['decimal'] = dumper
2815 c = dumper.Context(
2816 prec=prec, Emin=emin, Emax=emax,
2817 rounding=RoundingModes[ri],
2818 capitals=caps, clamp=clamp,
2819 flags=OrderedSignals[dumper][:fi],
2820 traps=OrderedSignals[dumper][:ti]
2821 )
2822 s = pickle.dumps(c, proto)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002823
Serhiy Storchakabad12572014-12-15 14:03:42 +02002824 # The other module loads
2825 sys.modules['decimal'] = loader
2826 d = pickle.loads(s)
2827 self.assertIsInstance(d, loader.Context)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002828
Serhiy Storchakabad12572014-12-15 14:03:42 +02002829 self.assertEqual(d.prec, prec)
2830 self.assertEqual(d.Emin, emin)
2831 self.assertEqual(d.Emax, emax)
2832 self.assertEqual(d.rounding, RoundingModes[ri])
2833 self.assertEqual(d.capitals, caps)
2834 self.assertEqual(d.clamp, clamp)
2835 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2836 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002837
Serhiy Storchakabad12572014-12-15 14:03:42 +02002838 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002839
2840 def test_equality_with_other_types(self):
2841 Decimal = self.decimal.Decimal
2842
2843 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2844 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2845
2846 def test_copy(self):
2847 # All copies should be deep
2848 Decimal = self.decimal.Decimal
2849 Context = self.decimal.Context
2850
2851 c = Context()
2852 d = c.copy()
2853 self.assertNotEqual(id(c), id(d))
2854 self.assertNotEqual(id(c.flags), id(d.flags))
2855 self.assertNotEqual(id(c.traps), id(d.traps))
2856 k1 = set(c.flags.keys())
2857 k2 = set(d.flags.keys())
2858 self.assertEqual(k1, k2)
2859 self.assertEqual(c.flags, d.flags)
2860
2861 def test__clamp(self):
2862 # In Python 3.2, the private attribute `_clamp` was made
2863 # public (issue 8540), with the old `_clamp` becoming a
2864 # property wrapping `clamp`. For the duration of Python 3.2
2865 # only, the attribute should be gettable/settable via both
2866 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2867 # removed.
2868 Context = self.decimal.Context
2869 c = Context()
2870 self.assertRaises(AttributeError, getattr, c, '_clamp')
2871
2872 def test_abs(self):
2873 Decimal = self.decimal.Decimal
2874 Context = self.decimal.Context
2875
2876 c = Context()
2877 d = c.abs(Decimal(-1))
2878 self.assertEqual(c.abs(-1), d)
2879 self.assertRaises(TypeError, c.abs, '-1')
2880
2881 def test_add(self):
2882 Decimal = self.decimal.Decimal
2883 Context = self.decimal.Context
2884
2885 c = Context()
2886 d = c.add(Decimal(1), Decimal(1))
2887 self.assertEqual(c.add(1, 1), d)
2888 self.assertEqual(c.add(Decimal(1), 1), d)
2889 self.assertEqual(c.add(1, Decimal(1)), d)
2890 self.assertRaises(TypeError, c.add, '1', 1)
2891 self.assertRaises(TypeError, c.add, 1, '1')
2892
2893 def test_compare(self):
2894 Decimal = self.decimal.Decimal
2895 Context = self.decimal.Context
2896
2897 c = Context()
2898 d = c.compare(Decimal(1), Decimal(1))
2899 self.assertEqual(c.compare(1, 1), d)
2900 self.assertEqual(c.compare(Decimal(1), 1), d)
2901 self.assertEqual(c.compare(1, Decimal(1)), d)
2902 self.assertRaises(TypeError, c.compare, '1', 1)
2903 self.assertRaises(TypeError, c.compare, 1, '1')
2904
2905 def test_compare_signal(self):
2906 Decimal = self.decimal.Decimal
2907 Context = self.decimal.Context
2908
2909 c = Context()
2910 d = c.compare_signal(Decimal(1), Decimal(1))
2911 self.assertEqual(c.compare_signal(1, 1), d)
2912 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2913 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2914 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2915 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2916
2917 def test_compare_total(self):
2918 Decimal = self.decimal.Decimal
2919 Context = self.decimal.Context
2920
2921 c = Context()
2922 d = c.compare_total(Decimal(1), Decimal(1))
2923 self.assertEqual(c.compare_total(1, 1), d)
2924 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2925 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2926 self.assertRaises(TypeError, c.compare_total, '1', 1)
2927 self.assertRaises(TypeError, c.compare_total, 1, '1')
2928
2929 def test_compare_total_mag(self):
2930 Decimal = self.decimal.Decimal
2931 Context = self.decimal.Context
2932
2933 c = Context()
2934 d = c.compare_total_mag(Decimal(1), Decimal(1))
2935 self.assertEqual(c.compare_total_mag(1, 1), d)
2936 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2937 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2938 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2939 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2940
2941 def test_copy_abs(self):
2942 Decimal = self.decimal.Decimal
2943 Context = self.decimal.Context
2944
2945 c = Context()
2946 d = c.copy_abs(Decimal(-1))
2947 self.assertEqual(c.copy_abs(-1), d)
2948 self.assertRaises(TypeError, c.copy_abs, '-1')
2949
2950 def test_copy_decimal(self):
2951 Decimal = self.decimal.Decimal
2952 Context = self.decimal.Context
2953
2954 c = Context()
2955 d = c.copy_decimal(Decimal(-1))
2956 self.assertEqual(c.copy_decimal(-1), d)
2957 self.assertRaises(TypeError, c.copy_decimal, '-1')
2958
2959 def test_copy_negate(self):
2960 Decimal = self.decimal.Decimal
2961 Context = self.decimal.Context
2962
2963 c = Context()
2964 d = c.copy_negate(Decimal(-1))
2965 self.assertEqual(c.copy_negate(-1), d)
2966 self.assertRaises(TypeError, c.copy_negate, '-1')
2967
2968 def test_copy_sign(self):
2969 Decimal = self.decimal.Decimal
2970 Context = self.decimal.Context
2971
2972 c = Context()
2973 d = c.copy_sign(Decimal(1), Decimal(-2))
2974 self.assertEqual(c.copy_sign(1, -2), d)
2975 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2976 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2977 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2978 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2979
2980 def test_divide(self):
2981 Decimal = self.decimal.Decimal
2982 Context = self.decimal.Context
2983
2984 c = Context()
2985 d = c.divide(Decimal(1), Decimal(2))
2986 self.assertEqual(c.divide(1, 2), d)
2987 self.assertEqual(c.divide(Decimal(1), 2), d)
2988 self.assertEqual(c.divide(1, Decimal(2)), d)
2989 self.assertRaises(TypeError, c.divide, '1', 2)
2990 self.assertRaises(TypeError, c.divide, 1, '2')
2991
2992 def test_divide_int(self):
2993 Decimal = self.decimal.Decimal
2994 Context = self.decimal.Context
2995
2996 c = Context()
2997 d = c.divide_int(Decimal(1), Decimal(2))
2998 self.assertEqual(c.divide_int(1, 2), d)
2999 self.assertEqual(c.divide_int(Decimal(1), 2), d)
3000 self.assertEqual(c.divide_int(1, Decimal(2)), d)
3001 self.assertRaises(TypeError, c.divide_int, '1', 2)
3002 self.assertRaises(TypeError, c.divide_int, 1, '2')
3003
3004 def test_divmod(self):
3005 Decimal = self.decimal.Decimal
3006 Context = self.decimal.Context
3007
3008 c = Context()
3009 d = c.divmod(Decimal(1), Decimal(2))
3010 self.assertEqual(c.divmod(1, 2), d)
3011 self.assertEqual(c.divmod(Decimal(1), 2), d)
3012 self.assertEqual(c.divmod(1, Decimal(2)), d)
3013 self.assertRaises(TypeError, c.divmod, '1', 2)
3014 self.assertRaises(TypeError, c.divmod, 1, '2')
3015
3016 def test_exp(self):
3017 Decimal = self.decimal.Decimal
3018 Context = self.decimal.Context
3019
3020 c = Context()
3021 d = c.exp(Decimal(10))
3022 self.assertEqual(c.exp(10), d)
3023 self.assertRaises(TypeError, c.exp, '10')
3024
3025 def test_fma(self):
3026 Decimal = self.decimal.Decimal
3027 Context = self.decimal.Context
3028
3029 c = Context()
3030 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3031 self.assertEqual(c.fma(2, 3, 4), d)
3032 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3033 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3034 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3035 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3036 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3037 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3038 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3039
3040 # Issue 12079 for Context.fma ...
3041 self.assertRaises(TypeError, c.fma,
3042 Decimal('Infinity'), Decimal(0), "not a decimal")
3043 self.assertRaises(TypeError, c.fma,
3044 Decimal(1), Decimal('snan'), 1.222)
3045 # ... and for Decimal.fma.
3046 self.assertRaises(TypeError, Decimal('Infinity').fma,
3047 Decimal(0), "not a decimal")
3048 self.assertRaises(TypeError, Decimal(1).fma,
3049 Decimal('snan'), 1.222)
3050
3051 def test_is_finite(self):
3052 Decimal = self.decimal.Decimal
3053 Context = self.decimal.Context
3054
3055 c = Context()
3056 d = c.is_finite(Decimal(10))
3057 self.assertEqual(c.is_finite(10), d)
3058 self.assertRaises(TypeError, c.is_finite, '10')
3059
3060 def test_is_infinite(self):
3061 Decimal = self.decimal.Decimal
3062 Context = self.decimal.Context
3063
3064 c = Context()
3065 d = c.is_infinite(Decimal(10))
3066 self.assertEqual(c.is_infinite(10), d)
3067 self.assertRaises(TypeError, c.is_infinite, '10')
3068
3069 def test_is_nan(self):
3070 Decimal = self.decimal.Decimal
3071 Context = self.decimal.Context
3072
3073 c = Context()
3074 d = c.is_nan(Decimal(10))
3075 self.assertEqual(c.is_nan(10), d)
3076 self.assertRaises(TypeError, c.is_nan, '10')
3077
3078 def test_is_normal(self):
3079 Decimal = self.decimal.Decimal
3080 Context = self.decimal.Context
3081
3082 c = Context()
3083 d = c.is_normal(Decimal(10))
3084 self.assertEqual(c.is_normal(10), d)
3085 self.assertRaises(TypeError, c.is_normal, '10')
3086
3087 def test_is_qnan(self):
3088 Decimal = self.decimal.Decimal
3089 Context = self.decimal.Context
3090
3091 c = Context()
3092 d = c.is_qnan(Decimal(10))
3093 self.assertEqual(c.is_qnan(10), d)
3094 self.assertRaises(TypeError, c.is_qnan, '10')
3095
3096 def test_is_signed(self):
3097 Decimal = self.decimal.Decimal
3098 Context = self.decimal.Context
3099
3100 c = Context()
3101 d = c.is_signed(Decimal(10))
3102 self.assertEqual(c.is_signed(10), d)
3103 self.assertRaises(TypeError, c.is_signed, '10')
3104
3105 def test_is_snan(self):
3106 Decimal = self.decimal.Decimal
3107 Context = self.decimal.Context
3108
3109 c = Context()
3110 d = c.is_snan(Decimal(10))
3111 self.assertEqual(c.is_snan(10), d)
3112 self.assertRaises(TypeError, c.is_snan, '10')
3113
3114 def test_is_subnormal(self):
3115 Decimal = self.decimal.Decimal
3116 Context = self.decimal.Context
3117
3118 c = Context()
3119 d = c.is_subnormal(Decimal(10))
3120 self.assertEqual(c.is_subnormal(10), d)
3121 self.assertRaises(TypeError, c.is_subnormal, '10')
3122
3123 def test_is_zero(self):
3124 Decimal = self.decimal.Decimal
3125 Context = self.decimal.Context
3126
3127 c = Context()
3128 d = c.is_zero(Decimal(10))
3129 self.assertEqual(c.is_zero(10), d)
3130 self.assertRaises(TypeError, c.is_zero, '10')
3131
3132 def test_ln(self):
3133 Decimal = self.decimal.Decimal
3134 Context = self.decimal.Context
3135
3136 c = Context()
3137 d = c.ln(Decimal(10))
3138 self.assertEqual(c.ln(10), d)
3139 self.assertRaises(TypeError, c.ln, '10')
3140
3141 def test_log10(self):
3142 Decimal = self.decimal.Decimal
3143 Context = self.decimal.Context
3144
3145 c = Context()
3146 d = c.log10(Decimal(10))
3147 self.assertEqual(c.log10(10), d)
3148 self.assertRaises(TypeError, c.log10, '10')
3149
3150 def test_logb(self):
3151 Decimal = self.decimal.Decimal
3152 Context = self.decimal.Context
3153
3154 c = Context()
3155 d = c.logb(Decimal(10))
3156 self.assertEqual(c.logb(10), d)
3157 self.assertRaises(TypeError, c.logb, '10')
3158
3159 def test_logical_and(self):
3160 Decimal = self.decimal.Decimal
3161 Context = self.decimal.Context
3162
3163 c = Context()
3164 d = c.logical_and(Decimal(1), Decimal(1))
3165 self.assertEqual(c.logical_and(1, 1), d)
3166 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3167 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3168 self.assertRaises(TypeError, c.logical_and, '1', 1)
3169 self.assertRaises(TypeError, c.logical_and, 1, '1')
3170
3171 def test_logical_invert(self):
3172 Decimal = self.decimal.Decimal
3173 Context = self.decimal.Context
3174
3175 c = Context()
3176 d = c.logical_invert(Decimal(1000))
3177 self.assertEqual(c.logical_invert(1000), d)
3178 self.assertRaises(TypeError, c.logical_invert, '1000')
3179
3180 def test_logical_or(self):
3181 Decimal = self.decimal.Decimal
3182 Context = self.decimal.Context
3183
3184 c = Context()
3185 d = c.logical_or(Decimal(1), Decimal(1))
3186 self.assertEqual(c.logical_or(1, 1), d)
3187 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3188 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3189 self.assertRaises(TypeError, c.logical_or, '1', 1)
3190 self.assertRaises(TypeError, c.logical_or, 1, '1')
3191
3192 def test_logical_xor(self):
3193 Decimal = self.decimal.Decimal
3194 Context = self.decimal.Context
3195
3196 c = Context()
3197 d = c.logical_xor(Decimal(1), Decimal(1))
3198 self.assertEqual(c.logical_xor(1, 1), d)
3199 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3200 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3201 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3202 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3203
3204 def test_max(self):
3205 Decimal = self.decimal.Decimal
3206 Context = self.decimal.Context
3207
3208 c = Context()
3209 d = c.max(Decimal(1), Decimal(2))
3210 self.assertEqual(c.max(1, 2), d)
3211 self.assertEqual(c.max(Decimal(1), 2), d)
3212 self.assertEqual(c.max(1, Decimal(2)), d)
3213 self.assertRaises(TypeError, c.max, '1', 2)
3214 self.assertRaises(TypeError, c.max, 1, '2')
3215
3216 def test_max_mag(self):
3217 Decimal = self.decimal.Decimal
3218 Context = self.decimal.Context
3219
3220 c = Context()
3221 d = c.max_mag(Decimal(1), Decimal(2))
3222 self.assertEqual(c.max_mag(1, 2), d)
3223 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3224 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3225 self.assertRaises(TypeError, c.max_mag, '1', 2)
3226 self.assertRaises(TypeError, c.max_mag, 1, '2')
3227
3228 def test_min(self):
3229 Decimal = self.decimal.Decimal
3230 Context = self.decimal.Context
3231
3232 c = Context()
3233 d = c.min(Decimal(1), Decimal(2))
3234 self.assertEqual(c.min(1, 2), d)
3235 self.assertEqual(c.min(Decimal(1), 2), d)
3236 self.assertEqual(c.min(1, Decimal(2)), d)
3237 self.assertRaises(TypeError, c.min, '1', 2)
3238 self.assertRaises(TypeError, c.min, 1, '2')
3239
3240 def test_min_mag(self):
3241 Decimal = self.decimal.Decimal
3242 Context = self.decimal.Context
3243
3244 c = Context()
3245 d = c.min_mag(Decimal(1), Decimal(2))
3246 self.assertEqual(c.min_mag(1, 2), d)
3247 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3248 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3249 self.assertRaises(TypeError, c.min_mag, '1', 2)
3250 self.assertRaises(TypeError, c.min_mag, 1, '2')
3251
3252 def test_minus(self):
3253 Decimal = self.decimal.Decimal
3254 Context = self.decimal.Context
3255
3256 c = Context()
3257 d = c.minus(Decimal(10))
3258 self.assertEqual(c.minus(10), d)
3259 self.assertRaises(TypeError, c.minus, '10')
3260
3261 def test_multiply(self):
3262 Decimal = self.decimal.Decimal
3263 Context = self.decimal.Context
3264
3265 c = Context()
3266 d = c.multiply(Decimal(1), Decimal(2))
3267 self.assertEqual(c.multiply(1, 2), d)
3268 self.assertEqual(c.multiply(Decimal(1), 2), d)
3269 self.assertEqual(c.multiply(1, Decimal(2)), d)
3270 self.assertRaises(TypeError, c.multiply, '1', 2)
3271 self.assertRaises(TypeError, c.multiply, 1, '2')
3272
3273 def test_next_minus(self):
3274 Decimal = self.decimal.Decimal
3275 Context = self.decimal.Context
3276
3277 c = Context()
3278 d = c.next_minus(Decimal(10))
3279 self.assertEqual(c.next_minus(10), d)
3280 self.assertRaises(TypeError, c.next_minus, '10')
3281
3282 def test_next_plus(self):
3283 Decimal = self.decimal.Decimal
3284 Context = self.decimal.Context
3285
3286 c = Context()
3287 d = c.next_plus(Decimal(10))
3288 self.assertEqual(c.next_plus(10), d)
3289 self.assertRaises(TypeError, c.next_plus, '10')
3290
3291 def test_next_toward(self):
3292 Decimal = self.decimal.Decimal
3293 Context = self.decimal.Context
3294
3295 c = Context()
3296 d = c.next_toward(Decimal(1), Decimal(2))
3297 self.assertEqual(c.next_toward(1, 2), d)
3298 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3299 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3300 self.assertRaises(TypeError, c.next_toward, '1', 2)
3301 self.assertRaises(TypeError, c.next_toward, 1, '2')
3302
3303 def test_normalize(self):
3304 Decimal = self.decimal.Decimal
3305 Context = self.decimal.Context
3306
3307 c = Context()
3308 d = c.normalize(Decimal(10))
3309 self.assertEqual(c.normalize(10), d)
3310 self.assertRaises(TypeError, c.normalize, '10')
3311
3312 def test_number_class(self):
3313 Decimal = self.decimal.Decimal
3314 Context = self.decimal.Context
3315
3316 c = Context()
3317 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3318 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3319 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3320
3321 def test_plus(self):
3322 Decimal = self.decimal.Decimal
3323 Context = self.decimal.Context
3324
3325 c = Context()
3326 d = c.plus(Decimal(10))
3327 self.assertEqual(c.plus(10), d)
3328 self.assertRaises(TypeError, c.plus, '10')
3329
3330 def test_power(self):
3331 Decimal = self.decimal.Decimal
3332 Context = self.decimal.Context
3333
3334 c = Context()
3335 d = c.power(Decimal(1), Decimal(4))
3336 self.assertEqual(c.power(1, 4), d)
3337 self.assertEqual(c.power(Decimal(1), 4), d)
3338 self.assertEqual(c.power(1, Decimal(4)), d)
3339 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3340 self.assertRaises(TypeError, c.power, '1', 4)
3341 self.assertRaises(TypeError, c.power, 1, '4')
3342 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3343
3344 def test_quantize(self):
3345 Decimal = self.decimal.Decimal
3346 Context = self.decimal.Context
3347
3348 c = Context()
3349 d = c.quantize(Decimal(1), Decimal(2))
3350 self.assertEqual(c.quantize(1, 2), d)
3351 self.assertEqual(c.quantize(Decimal(1), 2), d)
3352 self.assertEqual(c.quantize(1, Decimal(2)), d)
3353 self.assertRaises(TypeError, c.quantize, '1', 2)
3354 self.assertRaises(TypeError, c.quantize, 1, '2')
3355
3356 def test_remainder(self):
3357 Decimal = self.decimal.Decimal
3358 Context = self.decimal.Context
3359
3360 c = Context()
3361 d = c.remainder(Decimal(1), Decimal(2))
3362 self.assertEqual(c.remainder(1, 2), d)
3363 self.assertEqual(c.remainder(Decimal(1), 2), d)
3364 self.assertEqual(c.remainder(1, Decimal(2)), d)
3365 self.assertRaises(TypeError, c.remainder, '1', 2)
3366 self.assertRaises(TypeError, c.remainder, 1, '2')
3367
3368 def test_remainder_near(self):
3369 Decimal = self.decimal.Decimal
3370 Context = self.decimal.Context
3371
3372 c = Context()
3373 d = c.remainder_near(Decimal(1), Decimal(2))
3374 self.assertEqual(c.remainder_near(1, 2), d)
3375 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3376 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3377 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3378 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3379
3380 def test_rotate(self):
3381 Decimal = self.decimal.Decimal
3382 Context = self.decimal.Context
3383
3384 c = Context()
3385 d = c.rotate(Decimal(1), Decimal(2))
3386 self.assertEqual(c.rotate(1, 2), d)
3387 self.assertEqual(c.rotate(Decimal(1), 2), d)
3388 self.assertEqual(c.rotate(1, Decimal(2)), d)
3389 self.assertRaises(TypeError, c.rotate, '1', 2)
3390 self.assertRaises(TypeError, c.rotate, 1, '2')
3391
3392 def test_sqrt(self):
3393 Decimal = self.decimal.Decimal
3394 Context = self.decimal.Context
3395
3396 c = Context()
3397 d = c.sqrt(Decimal(10))
3398 self.assertEqual(c.sqrt(10), d)
3399 self.assertRaises(TypeError, c.sqrt, '10')
3400
3401 def test_same_quantum(self):
3402 Decimal = self.decimal.Decimal
3403 Context = self.decimal.Context
3404
3405 c = Context()
3406 d = c.same_quantum(Decimal(1), Decimal(2))
3407 self.assertEqual(c.same_quantum(1, 2), d)
3408 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3409 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3410 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3411 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3412
3413 def test_scaleb(self):
3414 Decimal = self.decimal.Decimal
3415 Context = self.decimal.Context
3416
3417 c = Context()
3418 d = c.scaleb(Decimal(1), Decimal(2))
3419 self.assertEqual(c.scaleb(1, 2), d)
3420 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3421 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3422 self.assertRaises(TypeError, c.scaleb, '1', 2)
3423 self.assertRaises(TypeError, c.scaleb, 1, '2')
3424
3425 def test_shift(self):
3426 Decimal = self.decimal.Decimal
3427 Context = self.decimal.Context
3428
3429 c = Context()
3430 d = c.shift(Decimal(1), Decimal(2))
3431 self.assertEqual(c.shift(1, 2), d)
3432 self.assertEqual(c.shift(Decimal(1), 2), d)
3433 self.assertEqual(c.shift(1, Decimal(2)), d)
3434 self.assertRaises(TypeError, c.shift, '1', 2)
3435 self.assertRaises(TypeError, c.shift, 1, '2')
3436
3437 def test_subtract(self):
3438 Decimal = self.decimal.Decimal
3439 Context = self.decimal.Context
3440
3441 c = Context()
3442 d = c.subtract(Decimal(1), Decimal(2))
3443 self.assertEqual(c.subtract(1, 2), d)
3444 self.assertEqual(c.subtract(Decimal(1), 2), d)
3445 self.assertEqual(c.subtract(1, Decimal(2)), d)
3446 self.assertRaises(TypeError, c.subtract, '1', 2)
3447 self.assertRaises(TypeError, c.subtract, 1, '2')
3448
3449 def test_to_eng_string(self):
3450 Decimal = self.decimal.Decimal
3451 Context = self.decimal.Context
3452
3453 c = Context()
3454 d = c.to_eng_string(Decimal(10))
3455 self.assertEqual(c.to_eng_string(10), d)
3456 self.assertRaises(TypeError, c.to_eng_string, '10')
3457
3458 def test_to_sci_string(self):
3459 Decimal = self.decimal.Decimal
3460 Context = self.decimal.Context
3461
3462 c = Context()
3463 d = c.to_sci_string(Decimal(10))
3464 self.assertEqual(c.to_sci_string(10), d)
3465 self.assertRaises(TypeError, c.to_sci_string, '10')
3466
3467 def test_to_integral_exact(self):
3468 Decimal = self.decimal.Decimal
3469 Context = self.decimal.Context
3470
3471 c = Context()
3472 d = c.to_integral_exact(Decimal(10))
3473 self.assertEqual(c.to_integral_exact(10), d)
3474 self.assertRaises(TypeError, c.to_integral_exact, '10')
3475
3476 def test_to_integral_value(self):
3477 Decimal = self.decimal.Decimal
3478 Context = self.decimal.Context
3479
3480 c = Context()
3481 d = c.to_integral_value(Decimal(10))
3482 self.assertEqual(c.to_integral_value(10), d)
3483 self.assertRaises(TypeError, c.to_integral_value, '10')
3484 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3485
3486class CContextAPItests(ContextAPItests):
3487 decimal = C
3488class PyContextAPItests(ContextAPItests):
3489 decimal = P
3490
3491class ContextWithStatement(unittest.TestCase):
3492 # Can't do these as docstrings until Python 2.6
3493 # as doctest can't handle __future__ statements
3494
3495 def test_localcontext(self):
3496 # Use a copy of the current context in the block
3497 getcontext = self.decimal.getcontext
3498 localcontext = self.decimal.localcontext
3499
3500 orig_ctx = getcontext()
3501 with localcontext() as enter_ctx:
3502 set_ctx = getcontext()
3503 final_ctx = getcontext()
3504 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3505 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3506 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3507
3508 def test_localcontextarg(self):
3509 # Use a copy of the supplied context in the block
3510 Context = self.decimal.Context
3511 getcontext = self.decimal.getcontext
3512 localcontext = self.decimal.localcontext
3513
3514 localcontext = self.decimal.localcontext
3515 orig_ctx = getcontext()
3516 new_ctx = Context(prec=42)
3517 with localcontext(new_ctx) as enter_ctx:
3518 set_ctx = getcontext()
3519 final_ctx = getcontext()
3520 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3521 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3522 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3523 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3524
3525 def test_nested_with_statements(self):
3526 # Use a copy of the supplied context in the block
3527 Decimal = self.decimal.Decimal
3528 Context = self.decimal.Context
3529 getcontext = self.decimal.getcontext
3530 localcontext = self.decimal.localcontext
3531 Clamped = self.decimal.Clamped
3532 Overflow = self.decimal.Overflow
3533
3534 orig_ctx = getcontext()
3535 orig_ctx.clear_flags()
3536 new_ctx = Context(Emax=384)
3537 with localcontext() as c1:
3538 self.assertEqual(c1.flags, orig_ctx.flags)
3539 self.assertEqual(c1.traps, orig_ctx.traps)
3540 c1.traps[Clamped] = True
3541 c1.Emin = -383
3542 self.assertNotEqual(orig_ctx.Emin, -383)
3543 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3544 self.assertTrue(c1.flags[Clamped])
3545 with localcontext(new_ctx) as c2:
3546 self.assertEqual(c2.flags, new_ctx.flags)
3547 self.assertEqual(c2.traps, new_ctx.traps)
3548 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3549 self.assertFalse(c2.flags[Clamped])
3550 self.assertTrue(c2.flags[Overflow])
3551 del c2
3552 self.assertFalse(c1.flags[Overflow])
3553 del c1
3554 self.assertNotEqual(orig_ctx.Emin, -383)
3555 self.assertFalse(orig_ctx.flags[Clamped])
3556 self.assertFalse(orig_ctx.flags[Overflow])
3557 self.assertFalse(new_ctx.flags[Clamped])
3558 self.assertFalse(new_ctx.flags[Overflow])
3559
3560 def test_with_statements_gc1(self):
3561 localcontext = self.decimal.localcontext
3562
3563 with localcontext() as c1:
3564 del c1
3565 with localcontext() as c2:
3566 del c2
3567 with localcontext() as c3:
3568 del c3
3569 with localcontext() as c4:
3570 del c4
3571
3572 def test_with_statements_gc2(self):
3573 localcontext = self.decimal.localcontext
3574
3575 with localcontext() as c1:
3576 with localcontext(c1) as c2:
3577 del c1
3578 with localcontext(c2) as c3:
3579 del c2
3580 with localcontext(c3) as c4:
3581 del c3
3582 del c4
3583
3584 def test_with_statements_gc3(self):
3585 Context = self.decimal.Context
3586 localcontext = self.decimal.localcontext
3587 getcontext = self.decimal.getcontext
3588 setcontext = self.decimal.setcontext
3589
3590 with localcontext() as c1:
3591 del c1
3592 n1 = Context(prec=1)
3593 setcontext(n1)
3594 with localcontext(n1) as c2:
3595 del n1
3596 self.assertEqual(c2.prec, 1)
3597 del c2
3598 n2 = Context(prec=2)
3599 setcontext(n2)
3600 del n2
3601 self.assertEqual(getcontext().prec, 2)
3602 n3 = Context(prec=3)
3603 setcontext(n3)
3604 self.assertEqual(getcontext().prec, 3)
3605 with localcontext(n3) as c3:
3606 del n3
3607 self.assertEqual(c3.prec, 3)
3608 del c3
3609 n4 = Context(prec=4)
3610 setcontext(n4)
3611 del n4
3612 self.assertEqual(getcontext().prec, 4)
3613 with localcontext() as c4:
3614 self.assertEqual(c4.prec, 4)
3615 del c4
3616
3617class CContextWithStatement(ContextWithStatement):
3618 decimal = C
3619class PyContextWithStatement(ContextWithStatement):
3620 decimal = P
3621
3622class ContextFlags(unittest.TestCase):
3623
3624 def test_flags_irrelevant(self):
3625 # check that the result (numeric result + flags raised) of an
3626 # arithmetic operation doesn't depend on the current flags
3627 Decimal = self.decimal.Decimal
3628 Context = self.decimal.Context
3629 Inexact = self.decimal.Inexact
3630 Rounded = self.decimal.Rounded
3631 Underflow = self.decimal.Underflow
3632 Clamped = self.decimal.Clamped
3633 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003634
3635 def raise_error(context, flag):
3636 if self.decimal == C:
3637 context.flags[flag] = True
3638 if context.traps[flag]:
3639 raise flag
3640 else:
3641 context._raise_error(flag)
3642
3643 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3644 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3645
3646 # operations that raise various flags, in the form (function, arglist)
3647 operations = [
3648 (context._apply, [Decimal("100E-425000010")]),
3649 (context.sqrt, [Decimal(2)]),
3650 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3651 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3652 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3653 ]
3654
3655 # try various flags individually, then a whole lot at once
3656 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3657 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3658
3659 for fn, args in operations:
3660 # find answer and flags raised using a clean context
3661 context.clear_flags()
3662 ans = fn(*args)
3663 flags = [k for k, v in context.flags.items() if v]
3664
3665 for extra_flags in flagsets:
3666 # set flags, before calling operation
3667 context.clear_flags()
3668 for flag in extra_flags:
3669 raise_error(context, flag)
3670 new_ans = fn(*args)
3671
3672 # flags that we expect to be set after the operation
3673 expected_flags = list(flags)
3674 for flag in extra_flags:
3675 if flag not in expected_flags:
3676 expected_flags.append(flag)
3677 expected_flags.sort(key=id)
3678
3679 # flags we actually got
3680 new_flags = [k for k,v in context.flags.items() if v]
3681 new_flags.sort(key=id)
3682
3683 self.assertEqual(ans, new_ans,
3684 "operation produces different answers depending on flags set: " +
3685 "expected %s, got %s." % (ans, new_ans))
3686 self.assertEqual(new_flags, expected_flags,
3687 "operation raises different flags depending on flags set: " +
3688 "expected %s, got %s" % (expected_flags, new_flags))
3689
3690 def test_flag_comparisons(self):
3691 Context = self.decimal.Context
3692 Inexact = self.decimal.Inexact
3693 Rounded = self.decimal.Rounded
3694
3695 c = Context()
3696
3697 # Valid SignalDict
3698 self.assertNotEqual(c.flags, c.traps)
3699 self.assertNotEqual(c.traps, c.flags)
3700
3701 c.flags = c.traps
3702 self.assertEqual(c.flags, c.traps)
3703 self.assertEqual(c.traps, c.flags)
3704
3705 c.flags[Rounded] = True
3706 c.traps = c.flags
3707 self.assertEqual(c.flags, c.traps)
3708 self.assertEqual(c.traps, c.flags)
3709
3710 d = {}
3711 d.update(c.flags)
3712 self.assertEqual(d, c.flags)
3713 self.assertEqual(c.flags, d)
3714
3715 d[Inexact] = True
3716 self.assertNotEqual(d, c.flags)
3717 self.assertNotEqual(c.flags, d)
3718
3719 # Invalid SignalDict
3720 d = {Inexact:False}
3721 self.assertNotEqual(d, c.flags)
3722 self.assertNotEqual(c.flags, d)
3723
3724 d = ["xyz"]
3725 self.assertNotEqual(d, c.flags)
3726 self.assertNotEqual(c.flags, d)
3727
3728 @requires_IEEE_754
3729 def test_float_operation(self):
3730 Decimal = self.decimal.Decimal
3731 FloatOperation = self.decimal.FloatOperation
3732 localcontext = self.decimal.localcontext
3733
3734 with localcontext() as c:
3735 ##### trap is off by default
3736 self.assertFalse(c.traps[FloatOperation])
3737
3738 # implicit conversion sets the flag
3739 c.clear_flags()
3740 self.assertEqual(Decimal(7.5), 7.5)
3741 self.assertTrue(c.flags[FloatOperation])
3742
3743 c.clear_flags()
3744 self.assertEqual(c.create_decimal(7.5), 7.5)
3745 self.assertTrue(c.flags[FloatOperation])
3746
3747 # explicit conversion does not set the flag
3748 c.clear_flags()
3749 x = Decimal.from_float(7.5)
3750 self.assertFalse(c.flags[FloatOperation])
3751 # comparison sets the flag
3752 self.assertEqual(x, 7.5)
3753 self.assertTrue(c.flags[FloatOperation])
3754
3755 c.clear_flags()
3756 x = c.create_decimal_from_float(7.5)
3757 self.assertFalse(c.flags[FloatOperation])
3758 self.assertEqual(x, 7.5)
3759 self.assertTrue(c.flags[FloatOperation])
3760
3761 ##### set the trap
3762 c.traps[FloatOperation] = True
3763
3764 # implicit conversion raises
3765 c.clear_flags()
3766 self.assertRaises(FloatOperation, Decimal, 7.5)
3767 self.assertTrue(c.flags[FloatOperation])
3768
3769 c.clear_flags()
3770 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3771 self.assertTrue(c.flags[FloatOperation])
3772
3773 # explicit conversion is silent
3774 c.clear_flags()
3775 x = Decimal.from_float(7.5)
3776 self.assertFalse(c.flags[FloatOperation])
3777
3778 c.clear_flags()
3779 x = c.create_decimal_from_float(7.5)
3780 self.assertFalse(c.flags[FloatOperation])
3781
3782 def test_float_comparison(self):
3783 Decimal = self.decimal.Decimal
3784 Context = self.decimal.Context
3785 FloatOperation = self.decimal.FloatOperation
3786 localcontext = self.decimal.localcontext
3787
3788 def assert_attr(a, b, attr, context, signal=None):
3789 context.clear_flags()
3790 f = getattr(a, attr)
3791 if signal == FloatOperation:
3792 self.assertRaises(signal, f, b)
3793 else:
3794 self.assertIs(f(b), True)
3795 self.assertTrue(context.flags[FloatOperation])
3796
3797 small_d = Decimal('0.25')
3798 big_d = Decimal('3.0')
3799 small_f = 0.25
3800 big_f = 3.0
3801
3802 zero_d = Decimal('0.0')
3803 neg_zero_d = Decimal('-0.0')
3804 zero_f = 0.0
3805 neg_zero_f = -0.0
3806
3807 inf_d = Decimal('Infinity')
3808 neg_inf_d = Decimal('-Infinity')
3809 inf_f = float('inf')
3810 neg_inf_f = float('-inf')
3811
3812 def doit(c, signal=None):
3813 # Order
3814 for attr in '__lt__', '__le__':
3815 assert_attr(small_d, big_f, attr, c, signal)
3816
3817 for attr in '__gt__', '__ge__':
3818 assert_attr(big_d, small_f, attr, c, signal)
3819
3820 # Equality
3821 assert_attr(small_d, small_f, '__eq__', c, None)
3822
3823 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3824 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3825
3826 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3827 assert_attr(zero_d, zero_f, '__eq__', c, None)
3828
3829 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3830 assert_attr(inf_d, inf_f, '__eq__', c, None)
3831
3832 # Inequality
3833 assert_attr(small_d, big_f, '__ne__', c, None)
3834
3835 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3836
3837 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3838 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3839
3840 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3841
3842 def test_containers(c, signal=None):
3843 c.clear_flags()
3844 s = set([100.0, Decimal('100.0')])
3845 self.assertEqual(len(s), 1)
3846 self.assertTrue(c.flags[FloatOperation])
3847
3848 c.clear_flags()
3849 if signal:
3850 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3851 else:
3852 s = sorted([10.0, Decimal('10.0')])
3853 self.assertTrue(c.flags[FloatOperation])
3854
3855 c.clear_flags()
3856 b = 10.0 in [Decimal('10.0'), 1.0]
3857 self.assertTrue(c.flags[FloatOperation])
3858
3859 c.clear_flags()
3860 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3861 self.assertTrue(c.flags[FloatOperation])
3862
3863 nc = Context()
3864 with localcontext(nc) as c:
3865 self.assertFalse(c.traps[FloatOperation])
3866 doit(c, signal=None)
3867 test_containers(c, signal=None)
3868
3869 c.traps[FloatOperation] = True
3870 doit(c, signal=FloatOperation)
3871 test_containers(c, signal=FloatOperation)
3872
3873 def test_float_operation_default(self):
3874 Decimal = self.decimal.Decimal
3875 Context = self.decimal.Context
3876 Inexact = self.decimal.Inexact
3877 FloatOperation= self.decimal.FloatOperation
3878
3879 context = Context()
3880 self.assertFalse(context.flags[FloatOperation])
3881 self.assertFalse(context.traps[FloatOperation])
3882
3883 context.clear_traps()
3884 context.traps[Inexact] = True
3885 context.traps[FloatOperation] = True
3886 self.assertTrue(context.traps[FloatOperation])
3887 self.assertTrue(context.traps[Inexact])
3888
3889class CContextFlags(ContextFlags):
3890 decimal = C
3891class PyContextFlags(ContextFlags):
3892 decimal = P
3893
3894class SpecialContexts(unittest.TestCase):
3895 """Test the context templates."""
3896
3897 def test_context_templates(self):
3898 BasicContext = self.decimal.BasicContext
3899 ExtendedContext = self.decimal.ExtendedContext
3900 getcontext = self.decimal.getcontext
3901 setcontext = self.decimal.setcontext
3902 InvalidOperation = self.decimal.InvalidOperation
3903 DivisionByZero = self.decimal.DivisionByZero
3904 Overflow = self.decimal.Overflow
3905 Underflow = self.decimal.Underflow
3906 Clamped = self.decimal.Clamped
3907
3908 assert_signals(self, BasicContext, 'traps',
3909 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3910 )
3911
3912 savecontext = getcontext().copy()
3913 basic_context_prec = BasicContext.prec
3914 extended_context_prec = ExtendedContext.prec
3915
3916 ex = None
3917 try:
3918 BasicContext.prec = ExtendedContext.prec = 441
3919 for template in BasicContext, ExtendedContext:
3920 setcontext(template)
3921 c = getcontext()
3922 self.assertIsNot(c, template)
3923 self.assertEqual(c.prec, 441)
3924 except Exception as e:
3925 ex = e.__class__
3926 finally:
3927 BasicContext.prec = basic_context_prec
3928 ExtendedContext.prec = extended_context_prec
3929 setcontext(savecontext)
3930 if ex:
3931 raise ex
3932
3933 def test_default_context(self):
3934 DefaultContext = self.decimal.DefaultContext
3935 BasicContext = self.decimal.BasicContext
3936 ExtendedContext = self.decimal.ExtendedContext
3937 getcontext = self.decimal.getcontext
3938 setcontext = self.decimal.setcontext
3939 InvalidOperation = self.decimal.InvalidOperation
3940 DivisionByZero = self.decimal.DivisionByZero
3941 Overflow = self.decimal.Overflow
3942
3943 self.assertEqual(BasicContext.prec, 9)
3944 self.assertEqual(ExtendedContext.prec, 9)
3945
3946 assert_signals(self, DefaultContext, 'traps',
3947 [InvalidOperation, DivisionByZero, Overflow]
3948 )
3949
3950 savecontext = getcontext().copy()
3951 default_context_prec = DefaultContext.prec
3952
3953 ex = None
3954 try:
3955 c = getcontext()
3956 saveprec = c.prec
3957
3958 DefaultContext.prec = 961
3959 c = getcontext()
3960 self.assertEqual(c.prec, saveprec)
3961
3962 setcontext(DefaultContext)
3963 c = getcontext()
3964 self.assertIsNot(c, DefaultContext)
3965 self.assertEqual(c.prec, 961)
3966 except Exception as e:
3967 ex = e.__class__
3968 finally:
3969 DefaultContext.prec = default_context_prec
3970 setcontext(savecontext)
3971 if ex:
3972 raise ex
3973
3974class CSpecialContexts(SpecialContexts):
3975 decimal = C
3976class PySpecialContexts(SpecialContexts):
3977 decimal = P
3978
3979class ContextInputValidation(unittest.TestCase):
3980
3981 def test_invalid_context(self):
3982 Context = self.decimal.Context
3983 DefaultContext = self.decimal.DefaultContext
3984
3985 c = DefaultContext.copy()
3986
3987 # prec, Emax
3988 for attr in ['prec', 'Emax']:
3989 setattr(c, attr, 999999)
3990 self.assertEqual(getattr(c, attr), 999999)
3991 self.assertRaises(ValueError, setattr, c, attr, -1)
3992 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3993
3994 # Emin
3995 setattr(c, 'Emin', -999999)
3996 self.assertEqual(getattr(c, 'Emin'), -999999)
3997 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3998 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3999
Stefan Krah1919b7e2012-03-21 18:25:23 +01004000 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
4001 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
4002 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
4003 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
4004
4005 # capitals, clamp
4006 for attr in ['capitals', 'clamp']:
4007 self.assertRaises(ValueError, setattr, c, attr, -1)
4008 self.assertRaises(ValueError, setattr, c, attr, 2)
4009 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4010
4011 # Invalid attribute
4012 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4013
4014 # Invalid signal dict
4015 self.assertRaises(TypeError, setattr, c, 'flags', [])
4016 self.assertRaises(KeyError, setattr, c, 'flags', {})
4017 self.assertRaises(KeyError, setattr, c, 'traps',
4018 {'InvalidOperation':0})
4019
4020 # Attributes cannot be deleted
4021 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4022 'flags', 'traps']:
4023 self.assertRaises(AttributeError, c.__delattr__, attr)
4024
4025 # Invalid attributes
4026 self.assertRaises(TypeError, getattr, c, 9)
4027 self.assertRaises(TypeError, setattr, c, 9)
4028
4029 # Invalid values in constructor
4030 self.assertRaises(TypeError, Context, rounding=999999)
4031 self.assertRaises(TypeError, Context, rounding='xyz')
4032 self.assertRaises(ValueError, Context, clamp=2)
4033 self.assertRaises(ValueError, Context, capitals=-1)
4034 self.assertRaises(KeyError, Context, flags=["P"])
4035 self.assertRaises(KeyError, Context, traps=["Q"])
4036
4037 # Type error in conversion
4038 self.assertRaises(TypeError, Context, flags=(0,1))
4039 self.assertRaises(TypeError, Context, traps=(1,0))
4040
4041class CContextInputValidation(ContextInputValidation):
4042 decimal = C
4043class PyContextInputValidation(ContextInputValidation):
4044 decimal = P
4045
4046class ContextSubclassing(unittest.TestCase):
4047
4048 def test_context_subclassing(self):
4049 decimal = self.decimal
4050 Decimal = decimal.Decimal
4051 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004052 Clamped = decimal.Clamped
4053 DivisionByZero = decimal.DivisionByZero
4054 Inexact = decimal.Inexact
4055 Overflow = decimal.Overflow
4056 Rounded = decimal.Rounded
4057 Subnormal = decimal.Subnormal
4058 Underflow = decimal.Underflow
4059 InvalidOperation = decimal.InvalidOperation
4060
4061 class MyContext(Context):
4062 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4063 capitals=None, clamp=None, flags=None,
4064 traps=None):
4065 Context.__init__(self)
4066 if prec is not None:
4067 self.prec = prec
4068 if rounding is not None:
4069 self.rounding = rounding
4070 if Emin is not None:
4071 self.Emin = Emin
4072 if Emax is not None:
4073 self.Emax = Emax
4074 if capitals is not None:
4075 self.capitals = capitals
4076 if clamp is not None:
4077 self.clamp = clamp
4078 if flags is not None:
4079 if isinstance(flags, list):
4080 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4081 self.flags = flags
4082 if traps is not None:
4083 if isinstance(traps, list):
4084 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4085 self.traps = traps
4086
4087 c = Context()
4088 d = MyContext()
4089 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4090 'flags', 'traps'):
4091 self.assertEqual(getattr(c, attr), getattr(d, attr))
4092
4093 # prec
4094 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4095 c = MyContext(prec=1)
4096 self.assertEqual(c.prec, 1)
4097 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4098
4099 # rounding
4100 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4101 c = MyContext(rounding=ROUND_DOWN, prec=1)
4102 self.assertEqual(c.rounding, ROUND_DOWN)
4103 self.assertEqual(c.plus(Decimal('9.9')), 9)
4104
4105 # Emin
4106 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4107 c = MyContext(Emin=-1, prec=1)
4108 self.assertEqual(c.Emin, -1)
4109 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4110 self.assertEqual(x, Decimal('0.0'))
4111 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4112 self.assertTrue(c.flags[signal])
4113
4114 # Emax
4115 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4116 c = MyContext(Emax=1, prec=1)
4117 self.assertEqual(c.Emax, 1)
4118 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4119 if self.decimal == C:
4120 for signal in (Inexact, Overflow, Rounded):
4121 self.assertTrue(c.flags[signal])
4122
4123 # capitals
4124 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4125 c = MyContext(capitals=0)
4126 self.assertEqual(c.capitals, 0)
4127 x = c.create_decimal('1E222')
4128 self.assertEqual(c.to_sci_string(x), '1e+222')
4129
4130 # clamp
4131 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4132 c = MyContext(clamp=1, Emax=99)
4133 self.assertEqual(c.clamp, 1)
4134 x = c.plus(Decimal('1e99'))
4135 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4136
4137 # flags
4138 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4139 c = MyContext(flags=[Rounded, DivisionByZero])
4140 for signal in (Rounded, DivisionByZero):
4141 self.assertTrue(c.flags[signal])
4142 c.clear_flags()
4143 for signal in OrderedSignals[decimal]:
4144 self.assertFalse(c.flags[signal])
4145
4146 # traps
4147 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4148 c = MyContext(traps=[Rounded, DivisionByZero])
4149 for signal in (Rounded, DivisionByZero):
4150 self.assertTrue(c.traps[signal])
4151 c.clear_traps()
4152 for signal in OrderedSignals[decimal]:
4153 self.assertFalse(c.traps[signal])
4154
4155class CContextSubclassing(ContextSubclassing):
4156 decimal = C
4157class PyContextSubclassing(ContextSubclassing):
4158 decimal = P
4159
4160@skip_if_extra_functionality
4161class CheckAttributes(unittest.TestCase):
4162
4163 def test_module_attributes(self):
4164
4165 # Architecture dependent context limits
4166 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4167 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4168 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4169 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4170
4171 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4172 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4173
4174 self.assertEqual(C.__version__, P.__version__)
Stefan Krah45059eb2013-11-24 19:44:57 +01004175 self.assertEqual(C.__libmpdec_version__, P.__libmpdec_version__)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004176
4177 x = dir(C)
4178 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02004179 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004180
4181 def test_context_attributes(self):
4182
4183 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4184 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4185 self.assertEqual(set(x) - set(y), set())
4186
4187 def test_decimal_attributes(self):
4188
4189 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4190 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4191 self.assertEqual(set(x) - set(y), set())
4192
4193class Coverage(unittest.TestCase):
4194
4195 def test_adjusted(self):
4196 Decimal = self.decimal.Decimal
4197
4198 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4199 # XXX raise?
4200 self.assertEqual(Decimal('nan').adjusted(), 0)
4201 self.assertEqual(Decimal('inf').adjusted(), 0)
4202
4203 def test_canonical(self):
4204 Decimal = self.decimal.Decimal
4205 getcontext = self.decimal.getcontext
4206
4207 x = Decimal(9).canonical()
4208 self.assertEqual(x, 9)
4209
4210 c = getcontext()
4211 x = c.canonical(Decimal(9))
4212 self.assertEqual(x, 9)
4213
4214 def test_context_repr(self):
4215 c = self.decimal.DefaultContext.copy()
4216
4217 c.prec = 425000000
4218 c.Emax = 425000000
4219 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004220 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004221 c.capitals = 0
4222 c.clamp = 1
4223 for sig in OrderedSignals[self.decimal]:
4224 c.flags[sig] = False
4225 c.traps[sig] = False
4226
4227 s = c.__repr__()
4228 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4229 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4230 "flags=[], traps=[])"
4231 self.assertEqual(s, t)
4232
4233 def test_implicit_context(self):
4234 Decimal = self.decimal.Decimal
4235 localcontext = self.decimal.localcontext
4236
4237 with localcontext() as c:
4238 c.prec = 1
4239 c.Emax = 1
4240 c.Emin = -1
4241
4242 # abs
4243 self.assertEqual(abs(Decimal("-10")), 10)
4244 # add
4245 self.assertEqual(Decimal("7") + 1, 8)
4246 # divide
4247 self.assertEqual(Decimal("10") / 5, 2)
4248 # divide_int
4249 self.assertEqual(Decimal("10") // 7, 1)
4250 # fma
4251 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4252 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4253 # three arg power
4254 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4255 # exp
4256 self.assertEqual(Decimal("1.01").exp(), 3)
4257 # is_normal
4258 self.assertIs(Decimal("0.01").is_normal(), False)
4259 # is_subnormal
4260 self.assertIs(Decimal("0.01").is_subnormal(), True)
4261 # ln
4262 self.assertEqual(Decimal("20").ln(), 3)
4263 # log10
4264 self.assertEqual(Decimal("20").log10(), 1)
4265 # logb
4266 self.assertEqual(Decimal("580").logb(), 2)
4267 # logical_invert
4268 self.assertEqual(Decimal("10").logical_invert(), 1)
4269 # minus
4270 self.assertEqual(-Decimal("-10"), 10)
4271 # multiply
4272 self.assertEqual(Decimal("2") * 4, 8)
4273 # next_minus
4274 self.assertEqual(Decimal("10").next_minus(), 9)
4275 # next_plus
4276 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4277 # normalize
4278 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4279 # number_class
4280 self.assertEqual(Decimal("10").number_class(), '+Normal')
4281 # plus
4282 self.assertEqual(+Decimal("-1"), -1)
4283 # remainder
4284 self.assertEqual(Decimal("10") % 7, 3)
4285 # subtract
4286 self.assertEqual(Decimal("10") - 7, 3)
4287 # to_integral_exact
4288 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4289
4290 # Boolean functions
4291 self.assertTrue(Decimal("1").is_canonical())
4292 self.assertTrue(Decimal("1").is_finite())
4293 self.assertTrue(Decimal("1").is_finite())
4294 self.assertTrue(Decimal("snan").is_snan())
4295 self.assertTrue(Decimal("-1").is_signed())
4296 self.assertTrue(Decimal("0").is_zero())
4297 self.assertTrue(Decimal("0").is_zero())
4298
4299 # Copy
4300 with localcontext() as c:
4301 c.prec = 10000
4302 x = 1228 ** 1523
4303 y = -Decimal(x)
4304
4305 z = y.copy_abs()
4306 self.assertEqual(z, x)
4307
4308 z = y.copy_negate()
4309 self.assertEqual(z, x)
4310
4311 z = y.copy_sign(Decimal(1))
4312 self.assertEqual(z, x)
4313
4314 def test_divmod(self):
4315 Decimal = self.decimal.Decimal
4316 localcontext = self.decimal.localcontext
4317 InvalidOperation = self.decimal.InvalidOperation
4318 DivisionByZero = self.decimal.DivisionByZero
4319
4320 with localcontext() as c:
4321 q, r = divmod(Decimal("10912837129"), 1001)
4322 self.assertEqual(q, Decimal('10901935'))
4323 self.assertEqual(r, Decimal('194'))
4324
4325 q, r = divmod(Decimal("NaN"), 7)
4326 self.assertTrue(q.is_nan() and r.is_nan())
4327
4328 c.traps[InvalidOperation] = False
4329 q, r = divmod(Decimal("NaN"), 7)
4330 self.assertTrue(q.is_nan() and r.is_nan())
4331
4332 c.traps[InvalidOperation] = False
4333 c.clear_flags()
4334 q, r = divmod(Decimal("inf"), Decimal("inf"))
4335 self.assertTrue(q.is_nan() and r.is_nan())
4336 self.assertTrue(c.flags[InvalidOperation])
4337
4338 c.clear_flags()
4339 q, r = divmod(Decimal("inf"), 101)
4340 self.assertTrue(q.is_infinite() and r.is_nan())
4341 self.assertTrue(c.flags[InvalidOperation])
4342
4343 c.clear_flags()
4344 q, r = divmod(Decimal(0), 0)
4345 self.assertTrue(q.is_nan() and r.is_nan())
4346 self.assertTrue(c.flags[InvalidOperation])
4347
4348 c.traps[DivisionByZero] = False
4349 c.clear_flags()
4350 q, r = divmod(Decimal(11), 0)
4351 self.assertTrue(q.is_infinite() and r.is_nan())
4352 self.assertTrue(c.flags[InvalidOperation] and
4353 c.flags[DivisionByZero])
4354
4355 def test_power(self):
4356 Decimal = self.decimal.Decimal
4357 localcontext = self.decimal.localcontext
4358 Overflow = self.decimal.Overflow
4359 Rounded = self.decimal.Rounded
4360
4361 with localcontext() as c:
4362 c.prec = 3
4363 c.clear_flags()
4364 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4365 self.assertTrue(c.flags[Rounded])
4366
4367 c.prec = 1
4368 c.Emax = 1
4369 c.Emin = -1
4370 c.clear_flags()
4371 c.traps[Overflow] = False
4372 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4373 self.assertTrue(c.flags[Overflow])
4374
4375 def test_quantize(self):
4376 Decimal = self.decimal.Decimal
4377 localcontext = self.decimal.localcontext
4378 InvalidOperation = self.decimal.InvalidOperation
4379
4380 with localcontext() as c:
4381 c.prec = 1
4382 c.Emax = 1
4383 c.Emin = -1
4384 c.traps[InvalidOperation] = False
4385 x = Decimal(99).quantize(Decimal("1e1"))
4386 self.assertTrue(x.is_nan())
4387
4388 def test_radix(self):
4389 Decimal = self.decimal.Decimal
4390 getcontext = self.decimal.getcontext
4391
4392 c = getcontext()
4393 self.assertEqual(Decimal("1").radix(), 10)
4394 self.assertEqual(c.radix(), 10)
4395
4396 def test_rop(self):
4397 Decimal = self.decimal.Decimal
4398
4399 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4400 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4401 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4402
4403 def test_round(self):
4404 # Python3 behavior: round() returns Decimal
4405 Decimal = self.decimal.Decimal
4406 getcontext = self.decimal.getcontext
4407
4408 c = getcontext()
4409 c.prec = 28
4410
4411 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4412 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4413 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4414 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4415 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4416
4417 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4418 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4419
4420 def test_create_decimal(self):
4421 c = self.decimal.Context()
4422 self.assertRaises(ValueError, c.create_decimal, ["%"])
4423
4424 def test_int(self):
4425 Decimal = self.decimal.Decimal
4426 localcontext = self.decimal.localcontext
4427
4428 with localcontext() as c:
4429 c.prec = 9999
4430 x = Decimal(1221**1271) / 10**3923
4431 self.assertEqual(int(x), 1)
4432 self.assertEqual(x.to_integral(), 2)
4433
4434 def test_copy(self):
4435 Context = self.decimal.Context
4436
4437 c = Context()
4438 c.prec = 10000
4439 x = -(1172 ** 1712)
4440
4441 y = c.copy_abs(x)
4442 self.assertEqual(y, -x)
4443
4444 y = c.copy_negate(x)
4445 self.assertEqual(y, -x)
4446
4447 y = c.copy_sign(x, 1)
4448 self.assertEqual(y, -x)
4449
4450class CCoverage(Coverage):
4451 decimal = C
4452class PyCoverage(Coverage):
4453 decimal = P
4454
4455class PyFunctionality(unittest.TestCase):
4456 """Extra functionality in decimal.py"""
4457
4458 def test_py_quantize_watchexp(self):
4459 # watchexp functionality
4460 Decimal = P.Decimal
4461 localcontext = P.localcontext
4462
4463 with localcontext() as c:
4464 c.prec = 1
4465 c.Emax = 1
4466 c.Emin = -1
4467 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4468 self.assertEqual(x, Decimal('1.00E+5'))
4469
4470 def test_py_alternate_formatting(self):
4471 # triples giving a format, a Decimal, and the expected result
4472 Decimal = P.Decimal
4473 localcontext = P.localcontext
4474
4475 test_values = [
4476 # Issue 7094: Alternate formatting (specified by #)
4477 ('.0e', '1.0', '1e+0'),
4478 ('#.0e', '1.0', '1.e+0'),
4479 ('.0f', '1.0', '1'),
4480 ('#.0f', '1.0', '1.'),
4481 ('g', '1.1', '1.1'),
4482 ('#g', '1.1', '1.1'),
4483 ('.0g', '1', '1'),
4484 ('#.0g', '1', '1.'),
4485 ('.0%', '1.0', '100%'),
4486 ('#.0%', '1.0', '100.%'),
4487 ]
4488 for fmt, d, result in test_values:
4489 self.assertEqual(format(Decimal(d), fmt), result)
4490
4491class PyWhitebox(unittest.TestCase):
4492 """White box testing for decimal.py"""
4493
4494 def test_py_exact_power(self):
4495 # Rarely exercised lines in _power_exact.
4496 Decimal = P.Decimal
4497 localcontext = P.localcontext
4498
4499 with localcontext() as c:
4500 c.prec = 8
4501 x = Decimal(2**16) ** Decimal("-0.5")
4502 self.assertEqual(x, Decimal('0.00390625'))
4503
4504 x = Decimal(2**16) ** Decimal("-0.6")
4505 self.assertEqual(x, Decimal('0.0012885819'))
4506
4507 x = Decimal("256e7") ** Decimal("-0.5")
4508
4509 x = Decimal(152587890625) ** Decimal('-0.0625')
4510 self.assertEqual(x, Decimal("0.2"))
4511
4512 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4513
4514 x = Decimal(5**2659) ** Decimal('-0.0625')
4515
4516 c.prec = 1
4517 x = Decimal("152587890625") ** Decimal('-0.5')
4518 c.prec = 201
4519 x = Decimal(2**578) ** Decimal("-0.5")
4520
4521 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004522 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004523 Decimal = P.Decimal
4524 DefaultContext = P.DefaultContext
4525 setcontext = P.setcontext
4526
4527 c = DefaultContext.copy()
4528 c.traps = dict((s, 0) for s in OrderedSignals[P])
4529 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004530
4531 d1 = Decimal('-25e55')
4532 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004533 d2 = Decimal('33e+33')
4534 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004535
4536 def checkSameDec(operation, useOther=False):
4537 if useOther:
4538 eval("d1." + operation + "(d2)")
4539 self.assertEqual(d1._sign, b1._sign)
4540 self.assertEqual(d1._int, b1._int)
4541 self.assertEqual(d1._exp, b1._exp)
4542 self.assertEqual(d2._sign, b2._sign)
4543 self.assertEqual(d2._int, b2._int)
4544 self.assertEqual(d2._exp, b2._exp)
4545 else:
4546 eval("d1." + operation + "()")
4547 self.assertEqual(d1._sign, b1._sign)
4548 self.assertEqual(d1._int, b1._int)
4549 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004550
4551 Decimal(d1)
4552 self.assertEqual(d1._sign, b1._sign)
4553 self.assertEqual(d1._int, b1._int)
4554 self.assertEqual(d1._exp, b1._exp)
4555
4556 checkSameDec("__abs__")
4557 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004558 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004559 checkSameDec("__eq__", True)
4560 checkSameDec("__ne__", True)
4561 checkSameDec("__le__", True)
4562 checkSameDec("__lt__", True)
4563 checkSameDec("__ge__", True)
4564 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004565 checkSameDec("__float__")
4566 checkSameDec("__floordiv__", True)
4567 checkSameDec("__hash__")
4568 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004569 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004570 checkSameDec("__mod__", True)
4571 checkSameDec("__mul__", True)
4572 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004573 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004574 checkSameDec("__pos__")
4575 checkSameDec("__pow__", True)
4576 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004577 checkSameDec("__rdivmod__", True)
4578 checkSameDec("__repr__")
4579 checkSameDec("__rfloordiv__", True)
4580 checkSameDec("__rmod__", True)
4581 checkSameDec("__rmul__", True)
4582 checkSameDec("__rpow__", True)
4583 checkSameDec("__rsub__", True)
4584 checkSameDec("__str__")
4585 checkSameDec("__sub__", True)
4586 checkSameDec("__truediv__", True)
4587 checkSameDec("adjusted")
4588 checkSameDec("as_tuple")
4589 checkSameDec("compare", True)
4590 checkSameDec("max", True)
4591 checkSameDec("min", True)
4592 checkSameDec("normalize")
4593 checkSameDec("quantize", True)
4594 checkSameDec("remainder_near", True)
4595 checkSameDec("same_quantum", True)
4596 checkSameDec("sqrt")
4597 checkSameDec("to_eng_string")
4598 checkSameDec("to_integral")
4599
Stefan Krah1919b7e2012-03-21 18:25:23 +01004600 def test_py_decimal_id(self):
4601 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004602
Stefan Krah1919b7e2012-03-21 18:25:23 +01004603 d = Decimal(45)
4604 e = Decimal(d)
4605 self.assertEqual(str(e), '45')
4606 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004607
Stefan Krah1919b7e2012-03-21 18:25:23 +01004608 def test_py_rescale(self):
4609 # Coverage
4610 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004611 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004612
Stefan Krah1919b7e2012-03-21 18:25:23 +01004613 with localcontext() as c:
4614 x = Decimal("NaN")._rescale(3, ROUND_UP)
4615 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004616
Stefan Krah1919b7e2012-03-21 18:25:23 +01004617 def test_py__round(self):
4618 # Coverage
4619 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004620
Stefan Krah1919b7e2012-03-21 18:25:23 +01004621 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004622
Stefan Krah1919b7e2012-03-21 18:25:23 +01004623class CFunctionality(unittest.TestCase):
4624 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004625
Stefan Krah1919b7e2012-03-21 18:25:23 +01004626 @requires_extra_functionality
4627 def test_c_ieee_context(self):
4628 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4629 IEEEContext = C.IEEEContext
4630 DECIMAL32 = C.DECIMAL32
4631 DECIMAL64 = C.DECIMAL64
4632 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004633
Stefan Krah1919b7e2012-03-21 18:25:23 +01004634 def assert_rest(self, context):
4635 self.assertEqual(context.clamp, 1)
4636 assert_signals(self, context, 'traps', [])
4637 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004638
Stefan Krah1919b7e2012-03-21 18:25:23 +01004639 c = IEEEContext(DECIMAL32)
4640 self.assertEqual(c.prec, 7)
4641 self.assertEqual(c.Emax, 96)
4642 self.assertEqual(c.Emin, -95)
4643 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004644
Stefan Krah1919b7e2012-03-21 18:25:23 +01004645 c = IEEEContext(DECIMAL64)
4646 self.assertEqual(c.prec, 16)
4647 self.assertEqual(c.Emax, 384)
4648 self.assertEqual(c.Emin, -383)
4649 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004650
Stefan Krah1919b7e2012-03-21 18:25:23 +01004651 c = IEEEContext(DECIMAL128)
4652 self.assertEqual(c.prec, 34)
4653 self.assertEqual(c.Emax, 6144)
4654 self.assertEqual(c.Emin, -6143)
4655 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004656
Stefan Krah1919b7e2012-03-21 18:25:23 +01004657 # Invalid values
4658 self.assertRaises(OverflowError, IEEEContext, 2**63)
4659 self.assertRaises(ValueError, IEEEContext, -1)
4660 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004661
Stefan Krah1919b7e2012-03-21 18:25:23 +01004662 @requires_extra_functionality
4663 def test_c_context(self):
4664 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004665
Stefan Krah1919b7e2012-03-21 18:25:23 +01004666 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4667 self.assertEqual(c._flags, C.DecClamped)
4668 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004669
Stefan Krah1919b7e2012-03-21 18:25:23 +01004670 @requires_extra_functionality
4671 def test_constants(self):
4672 # Condition flags
4673 cond = (
4674 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4675 C.DecDivisionImpossible, C.DecDivisionUndefined,
4676 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4677 C.DecInvalidOperation, C.DecMallocError,
4678 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4679 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004680 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004681
4682 # IEEEContext
4683 self.assertEqual(C.DECIMAL32, 32)
4684 self.assertEqual(C.DECIMAL64, 64)
4685 self.assertEqual(C.DECIMAL128, 128)
4686 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4687
Stefan Krah1919b7e2012-03-21 18:25:23 +01004688 # Conditions
4689 for i, v in enumerate(cond):
4690 self.assertEqual(v, 1<<i)
4691
4692 self.assertEqual(C.DecIEEEInvalidOperation,
4693 C.DecConversionSyntax|
4694 C.DecDivisionImpossible|
4695 C.DecDivisionUndefined|
4696 C.DecFpuError|
4697 C.DecInvalidContext|
4698 C.DecInvalidOperation|
4699 C.DecMallocError)
4700
4701 self.assertEqual(C.DecErrors,
4702 C.DecIEEEInvalidOperation|
4703 C.DecDivisionByZero)
4704
4705 self.assertEqual(C.DecTraps,
4706 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4707
4708class CWhitebox(unittest.TestCase):
4709 """Whitebox testing for _decimal"""
4710
4711 def test_bignum(self):
4712 # Not exactly whitebox, but too slow with pydecimal.
4713
4714 Decimal = C.Decimal
4715 localcontext = C.localcontext
4716
4717 b1 = 10**35
4718 b2 = 10**36
4719 with localcontext() as c:
4720 c.prec = 1000000
4721 for i in range(5):
4722 a = random.randrange(b1, b2)
4723 b = random.randrange(1000, 1200)
4724 x = a ** b
4725 y = Decimal(a) ** Decimal(b)
4726 self.assertEqual(x, y)
4727
4728 def test_invalid_construction(self):
4729 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4730
4731 def test_c_input_restriction(self):
4732 # Too large for _decimal to be converted exactly
4733 Decimal = C.Decimal
4734 InvalidOperation = C.InvalidOperation
4735 Context = C.Context
4736 localcontext = C.localcontext
4737
4738 with localcontext(Context()):
4739 self.assertRaises(InvalidOperation, Decimal,
4740 "1e9999999999999999999")
4741
4742 def test_c_context_repr(self):
4743 # This test is _decimal-only because flags are not printed
4744 # in the same order.
4745 DefaultContext = C.DefaultContext
4746 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004747
4748 c = DefaultContext.copy()
4749
4750 c.prec = 425000000
4751 c.Emax = 425000000
4752 c.Emin = -425000000
4753 c.rounding = ROUND_HALF_DOWN
4754 c.capitals = 0
4755 c.clamp = 1
4756 for sig in OrderedSignals[C]:
4757 c.flags[sig] = True
4758 c.traps[sig] = True
4759 c.flags[FloatOperation] = True
4760 c.traps[FloatOperation] = True
4761
4762 s = c.__repr__()
4763 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4764 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4765 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4766 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4767 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4768 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4769 self.assertEqual(s, t)
4770
4771 def test_c_context_errors(self):
4772 Context = C.Context
4773 InvalidOperation = C.InvalidOperation
4774 Overflow = C.Overflow
4775 FloatOperation = C.FloatOperation
4776 localcontext = C.localcontext
4777 getcontext = C.getcontext
4778 setcontext = C.setcontext
4779 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4780
4781 c = Context()
4782
4783 # SignalDict: input validation
4784 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4785 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4786 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4787 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4788 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4789 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4790 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4791 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4792
4793 # Test assignment from a signal dict with the correct length but
4794 # one invalid key.
4795 d = c.flags.copy()
4796 del d[FloatOperation]
4797 d["XYZ"] = 91283719
4798 self.assertRaises(KeyError, setattr, c, 'flags', d)
4799 self.assertRaises(KeyError, setattr, c, 'traps', d)
4800
4801 # Input corner cases
4802 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4803 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4804
4805 # prec, Emax, Emin
4806 for attr in ['prec', 'Emax']:
4807 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4808 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4809
4810 # prec, Emax, Emin in context constructor
4811 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4812 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4813 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4814
4815 # Overflow in conversion
4816 self.assertRaises(OverflowError, Context, prec=int_max+1)
4817 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4818 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004819 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4820 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4821
4822 # OverflowError, general ValueError
4823 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4824 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4825 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4826 if sys.platform != 'win32':
4827 self.assertRaises(ValueError, setattr, c, attr, int_max)
4828 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4829
Stefan Krah1919b7e2012-03-21 18:25:23 +01004830 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4831 if C.MAX_PREC == 425000000:
4832 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4833 int_max+1)
4834 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4835 int_max+1)
4836 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4837 -int_max-2)
4838
4839 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4840 if C.MAX_PREC == 425000000:
4841 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4842 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4843 1070000001)
4844 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4845 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4846 1070000001)
4847 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4848 -1070000001)
4849 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4850
4851 # capitals, clamp
4852 for attr in ['capitals', 'clamp']:
4853 self.assertRaises(ValueError, setattr, c, attr, -1)
4854 self.assertRaises(ValueError, setattr, c, attr, 2)
4855 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4856 if HAVE_CONFIG_64:
4857 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4858 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4859
4860 # Invalid local context
4861 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4862 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004863 self.assertRaises(TypeError, exec,
4864 'with localcontext(context=getcontext()): pass',
4865 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004866
4867 # setcontext
4868 saved_context = getcontext()
4869 self.assertRaises(TypeError, setcontext, "xyz")
4870 setcontext(saved_context)
4871
Stefan Krah59a4a932013-01-16 12:58:59 +01004872 def test_rounding_strings_interned(self):
4873
4874 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4875 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4876 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4877 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4878 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4879 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4880 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4881 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4882
Stefan Krah1919b7e2012-03-21 18:25:23 +01004883 @requires_extra_functionality
4884 def test_c_context_errors_extra(self):
4885 Context = C.Context
4886 InvalidOperation = C.InvalidOperation
4887 Overflow = C.Overflow
4888 localcontext = C.localcontext
4889 getcontext = C.getcontext
4890 setcontext = C.setcontext
4891 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4892
4893 c = Context()
4894
4895 # Input corner cases
4896 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4897
4898 # OverflowError, general ValueError
4899 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4900 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4901 if sys.platform != 'win32':
4902 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4903 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4904
4905 # OverflowError, general TypeError
4906 for attr in ('_flags', '_traps'):
4907 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4908 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4909 if sys.platform != 'win32':
4910 self.assertRaises(TypeError, setattr, c, attr, int_max)
4911 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4912
4913 # _allcr
4914 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4915 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4916 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4917 if HAVE_CONFIG_64:
4918 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4919 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4920
4921 # _flags, _traps
4922 for attr in ['_flags', '_traps']:
4923 self.assertRaises(TypeError, setattr, c, attr, 999999)
4924 self.assertRaises(TypeError, setattr, c, attr, 'x')
4925
4926 def test_c_valid_context(self):
4927 # These tests are for code coverage in _decimal.
4928 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004929 Clamped = C.Clamped
4930 Underflow = C.Underflow
4931 Inexact = C.Inexact
4932 Rounded = C.Rounded
4933 Subnormal = C.Subnormal
4934
4935 c = DefaultContext.copy()
4936
4937 # Exercise all getters and setters
4938 c.prec = 34
4939 c.rounding = ROUND_HALF_UP
4940 c.Emax = 3000
4941 c.Emin = -3000
4942 c.capitals = 1
4943 c.clamp = 0
4944
4945 self.assertEqual(c.prec, 34)
4946 self.assertEqual(c.rounding, ROUND_HALF_UP)
4947 self.assertEqual(c.Emin, -3000)
4948 self.assertEqual(c.Emax, 3000)
4949 self.assertEqual(c.capitals, 1)
4950 self.assertEqual(c.clamp, 0)
4951
4952 self.assertEqual(c.Etiny(), -3033)
4953 self.assertEqual(c.Etop(), 2967)
4954
4955 # Exercise all unsafe setters
4956 if C.MAX_PREC == 425000000:
4957 c._unsafe_setprec(999999999)
4958 c._unsafe_setemax(999999999)
4959 c._unsafe_setemin(-999999999)
4960 self.assertEqual(c.prec, 999999999)
4961 self.assertEqual(c.Emax, 999999999)
4962 self.assertEqual(c.Emin, -999999999)
4963
4964 @requires_extra_functionality
4965 def test_c_valid_context_extra(self):
4966 DefaultContext = C.DefaultContext
4967
4968 c = DefaultContext.copy()
4969 self.assertEqual(c._allcr, 1)
4970 c._allcr = 0
4971 self.assertEqual(c._allcr, 0)
4972
4973 def test_c_round(self):
4974 # Restricted input.
4975 Decimal = C.Decimal
4976 InvalidOperation = C.InvalidOperation
4977 localcontext = C.localcontext
4978 MAX_EMAX = C.MAX_EMAX
4979 MIN_ETINY = C.MIN_ETINY
4980 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4981
4982 with localcontext() as c:
4983 c.traps[InvalidOperation] = True
4984 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4985 -int_max-1)
4986 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4987 int_max)
4988 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4989 int(MAX_EMAX+1))
4990 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4991 -int(MIN_ETINY-1))
4992 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4993 -int_max-2)
4994 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4995 int_max+1)
4996
4997 def test_c_format(self):
4998 # Restricted input
4999 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01005000 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5001
5002 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
5003 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
5004 self.assertRaises(TypeError, Decimal(1).__format__, [])
5005
Stefan Kraheb8c4512013-01-24 15:22:33 +01005006 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
5007 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
5008 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
5009 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005010
5011 def test_c_integral(self):
5012 Decimal = C.Decimal
5013 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01005014 localcontext = C.localcontext
5015
5016 x = Decimal(10)
5017 self.assertEqual(x.to_integral(), 10)
5018 self.assertRaises(TypeError, x.to_integral, '10')
5019 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5020 self.assertRaises(TypeError, x.to_integral, 10)
5021
5022 self.assertEqual(x.to_integral_value(), 10)
5023 self.assertRaises(TypeError, x.to_integral_value, '10')
5024 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5025 self.assertRaises(TypeError, x.to_integral_value, 10)
5026
5027 self.assertEqual(x.to_integral_exact(), 10)
5028 self.assertRaises(TypeError, x.to_integral_exact, '10')
5029 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5030 self.assertRaises(TypeError, x.to_integral_exact, 10)
5031
5032 with localcontext() as c:
5033 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5034 self.assertEqual(x, Decimal('100000000000000000000000000'))
5035
5036 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5037 self.assertEqual(x, Decimal('100000000000000000000000000'))
5038
5039 c.traps[Inexact] = True
5040 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5041
5042 def test_c_funcs(self):
5043 # Invalid arguments
5044 Decimal = C.Decimal
5045 InvalidOperation = C.InvalidOperation
5046 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005047 getcontext = C.getcontext
5048 localcontext = C.localcontext
5049
5050 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5051
5052 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5053 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5054 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5055
Raymond Hettinger771ed762009-01-03 19:20:32 +00005056 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005057 TypeError,
5058 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005059 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005060 self.assertRaises(
5061 TypeError,
5062 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5063 )
5064 self.assertRaises(
5065 TypeError,
5066 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5067 )
5068 self.assertRaises(
5069 TypeError,
5070 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5071 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005072
Stefan Krah1919b7e2012-03-21 18:25:23 +01005073 with localcontext() as c:
5074 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005075
Stefan Krah1919b7e2012-03-21 18:25:23 +01005076 # Invalid arguments
5077 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5078 self.assertRaises(TypeError, c.canonical, 200)
5079 self.assertRaises(TypeError, c.is_canonical, 200)
5080 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5081 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005082
Stefan Krah1919b7e2012-03-21 18:25:23 +01005083 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5084 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005085
Stefan Krah1919b7e2012-03-21 18:25:23 +01005086 c.traps[DivisionByZero] = True
5087 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5088 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5089 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005090
Stefan Krah1919b7e2012-03-21 18:25:23 +01005091 c.clear_flags()
5092 c.traps[InvalidOperation] = True
5093 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5094 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5095 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005096
Stefan Krah1919b7e2012-03-21 18:25:23 +01005097 c.traps[InvalidOperation] = True
5098 c.prec = 2
5099 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005100
Stefan Krah040e3112012-12-15 22:33:33 +01005101 def test_va_args_exceptions(self):
5102 Decimal = C.Decimal
5103 Context = C.Context
5104
5105 x = Decimal("10001111111")
5106
5107 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5108 'logb', 'logical_invert', 'next_minus', 'next_plus',
5109 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5110 func = getattr(x, attr)
5111 self.assertRaises(TypeError, func, context="x")
5112 self.assertRaises(TypeError, func, "x", context=None)
5113
5114 for attr in ['compare', 'compare_signal', 'logical_and',
5115 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5116 'remainder_near', 'rotate', 'scaleb', 'shift']:
5117 func = getattr(x, attr)
5118 self.assertRaises(TypeError, func, context="x")
5119 self.assertRaises(TypeError, func, "x", context=None)
5120
5121 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5122 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5123 self.assertRaises(TypeError, x.to_integral, [], [])
5124
5125 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5126 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5127 self.assertRaises(TypeError, x.to_integral_value, [], [])
5128
5129 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5130 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5131 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5132
5133 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5134 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5135
5136 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5137 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5138 self.assertRaises(TypeError, x.quantize, 1, [], [])
5139
5140 c = Context()
5141 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5142 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5143 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5144
Stefan Krah1919b7e2012-03-21 18:25:23 +01005145 @requires_extra_functionality
5146 def test_c_context_templates(self):
5147 self.assertEqual(
5148 C.BasicContext._traps,
5149 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5150 C.DecUnderflow|C.DecClamped
5151 )
5152 self.assertEqual(
5153 C.DefaultContext._traps,
5154 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5155 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005156
Stefan Krah1919b7e2012-03-21 18:25:23 +01005157 @requires_extra_functionality
5158 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005159
Stefan Krah1919b7e2012-03-21 18:25:23 +01005160 # SignalDict coverage
5161 Context = C.Context
5162 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005163
Stefan Krah1919b7e2012-03-21 18:25:23 +01005164 InvalidOperation = C.InvalidOperation
5165 DivisionByZero = C.DivisionByZero
5166 Overflow = C.Overflow
5167 Subnormal = C.Subnormal
5168 Underflow = C.Underflow
5169 Rounded = C.Rounded
5170 Inexact = C.Inexact
5171 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005172
Stefan Krah1919b7e2012-03-21 18:25:23 +01005173 DecClamped = C.DecClamped
5174 DecInvalidOperation = C.DecInvalidOperation
5175 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005176
Stefan Krah1919b7e2012-03-21 18:25:23 +01005177 def assertIsExclusivelySet(signal, signal_dict):
5178 for sig in signal_dict:
5179 if sig == signal:
5180 self.assertTrue(signal_dict[sig])
5181 else:
5182 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005183
Stefan Krah1919b7e2012-03-21 18:25:23 +01005184 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005185
Stefan Krah1919b7e2012-03-21 18:25:23 +01005186 # Signal dict methods
5187 self.assertTrue(Overflow in c.traps)
5188 c.clear_traps()
5189 for k in c.traps.keys():
5190 c.traps[k] = True
5191 for v in c.traps.values():
5192 self.assertTrue(v)
5193 c.clear_traps()
5194 for k, v in c.traps.items():
5195 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005196
Stefan Krah1919b7e2012-03-21 18:25:23 +01005197 self.assertFalse(c.flags.get(Overflow))
5198 self.assertIs(c.flags.get("x"), None)
5199 self.assertEqual(c.flags.get("x", "y"), "y")
5200 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005201
Stefan Krah1919b7e2012-03-21 18:25:23 +01005202 self.assertEqual(len(c.flags), len(c.traps))
5203 s = sys.getsizeof(c.flags)
5204 s = sys.getsizeof(c.traps)
5205 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005206
Stefan Krah1919b7e2012-03-21 18:25:23 +01005207 # Set flags/traps.
5208 c.clear_flags()
5209 c._flags = DecClamped
5210 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005211
Stefan Krah1919b7e2012-03-21 18:25:23 +01005212 c.clear_traps()
5213 c._traps = DecInvalidOperation
5214 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005215
Stefan Krah1919b7e2012-03-21 18:25:23 +01005216 # Set flags/traps from dictionary.
5217 c.clear_flags()
5218 d = c.flags.copy()
5219 d[DivisionByZero] = True
5220 c.flags = d
5221 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005222
Stefan Krah1919b7e2012-03-21 18:25:23 +01005223 c.clear_traps()
5224 d = c.traps.copy()
5225 d[Underflow] = True
5226 c.traps = d
5227 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005228
Stefan Krah1919b7e2012-03-21 18:25:23 +01005229 # Random constructors
5230 IntSignals = {
5231 Clamped: C.DecClamped,
5232 Rounded: C.DecRounded,
5233 Inexact: C.DecInexact,
5234 Subnormal: C.DecSubnormal,
5235 Underflow: C.DecUnderflow,
5236 Overflow: C.DecOverflow,
5237 DivisionByZero: C.DecDivisionByZero,
5238 InvalidOperation: C.DecIEEEInvalidOperation
5239 }
5240 IntCond = [
5241 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5242 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5243 C.DecConversionSyntax,
5244 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005245
Stefan Krah1919b7e2012-03-21 18:25:23 +01005246 lim = len(OrderedSignals[C])
5247 for r in range(lim):
5248 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005249 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005250 flags = random.sample(OrderedSignals[C], r)
5251 traps = random.sample(OrderedSignals[C], t)
5252 prec = random.randrange(1, 10000)
5253 emin = random.randrange(-10000, 0)
5254 emax = random.randrange(0, 10000)
5255 clamp = random.randrange(0, 2)
5256 caps = random.randrange(0, 2)
5257 cr = random.randrange(0, 2)
5258 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5259 capitals=caps, clamp=clamp, flags=list(flags),
5260 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005261
Stefan Krah1919b7e2012-03-21 18:25:23 +01005262 self.assertEqual(c.prec, prec)
5263 self.assertEqual(c.rounding, round)
5264 self.assertEqual(c.Emin, emin)
5265 self.assertEqual(c.Emax, emax)
5266 self.assertEqual(c.capitals, caps)
5267 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005268
Stefan Krah1919b7e2012-03-21 18:25:23 +01005269 f = 0
5270 for x in flags:
5271 f |= IntSignals[x]
5272 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005273
Stefan Krah1919b7e2012-03-21 18:25:23 +01005274 f = 0
5275 for x in traps:
5276 f |= IntSignals[x]
5277 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005278
Stefan Krah1919b7e2012-03-21 18:25:23 +01005279 for cond in IntCond:
5280 c._flags = cond
5281 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5282 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005283
Stefan Krah1919b7e2012-03-21 18:25:23 +01005284 for cond in IntCond:
5285 c._traps = cond
5286 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5287 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005288
Stefan Krah1919b7e2012-03-21 18:25:23 +01005289 def test_invalid_override(self):
5290 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005291
Stefan Krah1919b7e2012-03-21 18:25:23 +01005292 try:
5293 from locale import CHAR_MAX
5294 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06005295 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson84230a12010-02-18 14:49:50 +00005296
Stefan Krah1919b7e2012-03-21 18:25:23 +01005297 def make_grouping(lst):
5298 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005299
Stefan Krah1919b7e2012-03-21 18:25:23 +01005300 def get_fmt(x, override=None, fmt='n'):
5301 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005302
Stefan Krah1919b7e2012-03-21 18:25:23 +01005303 invalid_grouping = {
5304 'decimal_point' : ',',
5305 'grouping' : make_grouping([255, 255, 0]),
5306 'thousands_sep' : ','
5307 }
5308 invalid_dot = {
5309 'decimal_point' : 'xxxxx',
5310 'grouping' : make_grouping([3, 3, 0]),
5311 'thousands_sep' : ','
5312 }
5313 invalid_sep = {
5314 'decimal_point' : '.',
5315 'grouping' : make_grouping([3, 3, 0]),
5316 'thousands_sep' : 'yyyyy'
5317 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005318
Stefan Krah1919b7e2012-03-21 18:25:23 +01005319 if CHAR_MAX == 127: # negative grouping in override
5320 self.assertRaises(ValueError, get_fmt, 12345,
5321 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005322
Stefan Krah1919b7e2012-03-21 18:25:23 +01005323 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5324 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005325
Stefan Krah0774e9b2012-04-05 15:21:58 +02005326 def test_exact_conversion(self):
5327 Decimal = C.Decimal
5328 localcontext = C.localcontext
5329 InvalidOperation = C.InvalidOperation
5330
5331 with localcontext() as c:
5332
5333 c.traps[InvalidOperation] = True
5334
5335 # Clamped
5336 x = "0e%d" % sys.maxsize
5337 self.assertRaises(InvalidOperation, Decimal, x)
5338
5339 x = "0e%d" % (-sys.maxsize-1)
5340 self.assertRaises(InvalidOperation, Decimal, x)
5341
5342 # Overflow
5343 x = "1e%d" % sys.maxsize
5344 self.assertRaises(InvalidOperation, Decimal, x)
5345
5346 # Underflow
5347 x = "1e%d" % (-sys.maxsize-1)
5348 self.assertRaises(InvalidOperation, Decimal, x)
5349
Stefan Krahff3eca02012-04-05 15:46:19 +02005350 def test_from_tuple(self):
5351 Decimal = C.Decimal
5352 localcontext = C.localcontext
5353 InvalidOperation = C.InvalidOperation
5354 Overflow = C.Overflow
5355 Underflow = C.Underflow
5356
5357 with localcontext() as c:
5358
5359 c.traps[InvalidOperation] = True
5360 c.traps[Overflow] = True
5361 c.traps[Underflow] = True
5362
5363 # SSIZE_MAX
5364 x = (1, (), sys.maxsize)
5365 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5366 self.assertRaises(InvalidOperation, Decimal, x)
5367
5368 x = (1, (0, 1, 2), sys.maxsize)
5369 self.assertRaises(Overflow, c.create_decimal, x)
5370 self.assertRaises(InvalidOperation, Decimal, x)
5371
5372 # SSIZE_MIN
5373 x = (1, (), -sys.maxsize-1)
5374 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5375 self.assertRaises(InvalidOperation, Decimal, x)
5376
5377 x = (1, (0, 1, 2), -sys.maxsize-1)
5378 self.assertRaises(Underflow, c.create_decimal, x)
5379 self.assertRaises(InvalidOperation, Decimal, x)
5380
5381 # OverflowError
5382 x = (1, (), sys.maxsize+1)
5383 self.assertRaises(OverflowError, c.create_decimal, x)
5384 self.assertRaises(OverflowError, Decimal, x)
5385
5386 x = (1, (), -sys.maxsize-2)
5387 self.assertRaises(OverflowError, c.create_decimal, x)
5388 self.assertRaises(OverflowError, Decimal, x)
5389
5390 # Specials
5391 x = (1, (), "N")
5392 self.assertEqual(str(Decimal(x)), '-sNaN')
5393 x = (1, (0,), "N")
5394 self.assertEqual(str(Decimal(x)), '-sNaN')
5395 x = (1, (0, 1), "N")
5396 self.assertEqual(str(Decimal(x)), '-sNaN1')
5397
Stefan Krah891ca9e2013-05-29 19:14:17 +02005398 def test_sizeof(self):
5399 Decimal = C.Decimal
5400 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5401
5402 self.assertGreater(Decimal(0).__sizeof__(), 0)
5403 if HAVE_CONFIG_64:
5404 x = Decimal(10**(19*24)).__sizeof__()
5405 y = Decimal(10**(19*25)).__sizeof__()
5406 self.assertEqual(y, x+8)
5407 else:
5408 x = Decimal(10**(9*24)).__sizeof__()
5409 y = Decimal(10**(9*25)).__sizeof__()
5410 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005411
Stefan Krah1919b7e2012-03-21 18:25:23 +01005412all_tests = [
5413 CExplicitConstructionTest, PyExplicitConstructionTest,
5414 CImplicitConstructionTest, PyImplicitConstructionTest,
5415 CFormatTest, PyFormatTest,
5416 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5417 CThreadingTest, PyThreadingTest,
5418 CUsabilityTest, PyUsabilityTest,
5419 CPythonAPItests, PyPythonAPItests,
5420 CContextAPItests, PyContextAPItests,
5421 CContextWithStatement, PyContextWithStatement,
5422 CContextFlags, PyContextFlags,
5423 CSpecialContexts, PySpecialContexts,
5424 CContextInputValidation, PyContextInputValidation,
5425 CContextSubclassing, PyContextSubclassing,
5426 CCoverage, PyCoverage,
5427 CFunctionality, PyFunctionality,
5428 CWhitebox, PyWhitebox,
5429 CIBMTestCases, PyIBMTestCases,
5430]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005431
Stefan Krah1919b7e2012-03-21 18:25:23 +01005432# Delete C tests if _decimal.so is not present.
5433if not C:
5434 all_tests = all_tests[1::2]
5435else:
5436 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005437
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005438
Zachary Ware66f29282014-06-02 16:01:29 -05005439def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005440 """ Execute the tests.
5441
Raymond Hettingered20ad82004-09-04 20:09:13 +00005442 Runs all arithmetic tests if arith is True or if the "decimal" resource
5443 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005444 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005445
Stefan Krah1919b7e2012-03-21 18:25:23 +01005446 init(C)
5447 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005448 global TEST_ALL, DEBUG
Zachary Ware66f29282014-06-02 16:01:29 -05005449 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005450 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005451
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005452 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005453 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005454 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005455 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005456
5457 # Dynamically build custom test definition for each file in the test
5458 # directory and add the definitions to the DecimalTest class. This
5459 # procedure insures that new files do not get skipped.
5460 for filename in os.listdir(directory):
5461 if '.decTest' not in filename or filename.startswith("."):
5462 continue
5463 head, tail = filename.split('.')
5464 if todo_tests is not None and head not in todo_tests:
5465 continue
5466 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005467 setattr(CIBMTestCases, 'test_' + head, tester)
5468 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005469 del filename, head, tail, tester
5470
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005471
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005472 try:
5473 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005474 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005475 from doctest import IGNORE_EXCEPTION_DETAIL
5476 savedecimal = sys.modules['decimal']
5477 if C:
5478 sys.modules['decimal'] = C
5479 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5480 sys.modules['decimal'] = P
5481 run_doctest(P, verbose)
5482 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005483 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005484 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5485 P.setcontext(ORIGINAL_CONTEXT[P])
5486 if not C:
5487 warnings.warn('C tests skipped: no module named _decimal.',
5488 UserWarning)
5489 if not orig_sys_decimal is sys.modules['decimal']:
5490 raise TestFailed("Internal error: unbalanced number of changes to "
5491 "sys.modules['decimal'].")
5492
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005493
5494if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005495 import optparse
5496 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5497 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5498 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5499 (opt, args) = p.parse_args()
5500
5501 if opt.skip:
5502 test_main(arith=False, verbose=True)
5503 elif args:
5504 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005505 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005506 test_main(arith=True, verbose=True)