blob: b4c8c3411e1684d031b1cca28f5a197e1ae6f2eb [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):
2409 Decimal = self.decimal.Decimal
2410
2411 savedecimal = sys.modules['decimal']
2412
2413 # Round trip
2414 sys.modules['decimal'] = self.decimal
2415 d = Decimal('-3.141590000')
2416 p = pickle.dumps(d)
2417 e = pickle.loads(p)
2418 self.assertEqual(d, e)
2419
2420 if C:
2421 # Test interchangeability
2422 x = C.Decimal('-3.123e81723')
2423 y = P.Decimal('-3.123e81723')
2424
2425 sys.modules['decimal'] = C
2426 sx = pickle.dumps(x)
2427 sys.modules['decimal'] = P
2428 r = pickle.loads(sx)
2429 self.assertIsInstance(r, P.Decimal)
2430 self.assertEqual(r, y)
2431
2432 sys.modules['decimal'] = P
2433 sy = pickle.dumps(y)
2434 sys.modules['decimal'] = C
2435 r = pickle.loads(sy)
2436 self.assertIsInstance(r, C.Decimal)
2437 self.assertEqual(r, x)
2438
Stefan Krah8fb74a32014-04-29 18:24:50 +02002439 x = C.Decimal('-3.123e81723').as_tuple()
2440 y = P.Decimal('-3.123e81723').as_tuple()
2441
2442 sys.modules['decimal'] = C
2443 sx = pickle.dumps(x)
2444 sys.modules['decimal'] = P
2445 r = pickle.loads(sx)
2446 self.assertIsInstance(r, P.DecimalTuple)
2447 self.assertEqual(r, y)
2448
2449 sys.modules['decimal'] = P
2450 sy = pickle.dumps(y)
2451 sys.modules['decimal'] = C
2452 r = pickle.loads(sy)
2453 self.assertIsInstance(r, C.DecimalTuple)
2454 self.assertEqual(r, x)
2455
Stefan Krah1919b7e2012-03-21 18:25:23 +01002456 sys.modules['decimal'] = savedecimal
2457
2458 def test_int(self):
2459 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002460
2461 for x in range(-250, 250):
2462 s = '%0.2f' % (x / 100.0)
2463 # should work the same as for floats
2464 self.assertEqual(int(Decimal(s)), int(float(s)))
2465 # should work the same as to_integral in the ROUND_DOWN mode
2466 d = Decimal(s)
2467 r = d.to_integral(ROUND_DOWN)
2468 self.assertEqual(Decimal(int(d)), r)
2469
2470 self.assertRaises(ValueError, int, Decimal('-nan'))
2471 self.assertRaises(ValueError, int, Decimal('snan'))
2472 self.assertRaises(OverflowError, int, Decimal('inf'))
2473 self.assertRaises(OverflowError, int, Decimal('-inf'))
2474
2475 def test_trunc(self):
2476 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002477
2478 for x in range(-250, 250):
2479 s = '%0.2f' % (x / 100.0)
2480 # should work the same as for floats
2481 self.assertEqual(int(Decimal(s)), int(float(s)))
2482 # should work the same as to_integral in the ROUND_DOWN mode
2483 d = Decimal(s)
2484 r = d.to_integral(ROUND_DOWN)
2485 self.assertEqual(Decimal(math.trunc(d)), r)
2486
2487 def test_from_float(self):
2488
2489 Decimal = self.decimal.Decimal
2490
2491 class MyDecimal(Decimal):
2492 pass
2493
2494 self.assertTrue(issubclass(MyDecimal, Decimal))
2495
2496 r = MyDecimal.from_float(0.1)
2497 self.assertEqual(type(r), MyDecimal)
2498 self.assertEqual(str(r),
2499 '0.1000000000000000055511151231257827021181583404541015625')
2500 bigint = 12345678901234567890123456789
2501 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2502 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2503 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2504 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2505 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2506 str(Decimal('NaN')))
2507 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2508 str(Decimal('Infinity')))
2509 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2510 str(Decimal('-Infinity')))
2511 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2512 for i in range(200):
2513 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2514 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2515
2516 def test_create_decimal_from_float(self):
2517 Decimal = self.decimal.Decimal
2518 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002519 Inexact = self.decimal.Inexact
2520
2521 context = Context(prec=5, rounding=ROUND_DOWN)
2522 self.assertEqual(
2523 context.create_decimal_from_float(math.pi),
2524 Decimal('3.1415')
2525 )
2526 context = Context(prec=5, rounding=ROUND_UP)
2527 self.assertEqual(
2528 context.create_decimal_from_float(math.pi),
2529 Decimal('3.1416')
2530 )
2531 context = Context(prec=5, traps=[Inexact])
2532 self.assertRaises(
2533 Inexact,
2534 context.create_decimal_from_float,
2535 math.pi
2536 )
2537 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2538 "Decimal('-0')")
2539 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2540 "Decimal('1')")
2541 self.assertEqual(repr(context.create_decimal_from_float(10)),
2542 "Decimal('10')")
2543
2544 def test_quantize(self):
2545 Decimal = self.decimal.Decimal
2546 Context = self.decimal.Context
2547 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002548
2549 c = Context(Emax=99999, Emin=-99999)
2550 self.assertEqual(
2551 Decimal('7.335').quantize(Decimal('.01')),
2552 Decimal('7.34')
2553 )
2554 self.assertEqual(
2555 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2556 Decimal('7.33')
2557 )
2558 self.assertRaises(
2559 InvalidOperation,
2560 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2561 )
2562
2563 c = Context()
2564 d = Decimal("0.871831e800")
2565 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2566 self.assertEqual(x, Decimal('8.71E+799'))
2567
2568 def test_complex(self):
2569 Decimal = self.decimal.Decimal
2570
2571 x = Decimal("9.8182731e181273")
2572 self.assertEqual(x.real, x)
2573 self.assertEqual(x.imag, 0)
2574 self.assertEqual(x.conjugate(), x)
2575
2576 x = Decimal("1")
2577 self.assertEqual(complex(x), complex(float(1)))
2578
2579 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2580 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2581 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2582 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2583
2584 def test_named_parameters(self):
2585 D = self.decimal.Decimal
2586 Context = self.decimal.Context
2587 localcontext = self.decimal.localcontext
2588 InvalidOperation = self.decimal.InvalidOperation
2589 Overflow = self.decimal.Overflow
2590
2591 xc = Context()
2592 xc.prec = 1
2593 xc.Emax = 1
2594 xc.Emin = -1
2595
2596 with localcontext() as c:
2597 c.clear_flags()
2598
2599 self.assertEqual(D(9, xc), 9)
2600 self.assertEqual(D(9, context=xc), 9)
2601 self.assertEqual(D(context=xc, value=9), 9)
2602 self.assertEqual(D(context=xc), 0)
2603 xc.clear_flags()
2604 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2605 self.assertTrue(xc.flags[InvalidOperation])
2606 self.assertFalse(c.flags[InvalidOperation])
2607
2608 xc.clear_flags()
2609 self.assertEqual(D(2).exp(context=xc), 7)
2610 self.assertRaises(Overflow, D(8).exp, context=xc)
2611 self.assertTrue(xc.flags[Overflow])
2612 self.assertFalse(c.flags[Overflow])
2613
2614 xc.clear_flags()
2615 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2616 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2617 self.assertTrue(xc.flags[InvalidOperation])
2618 self.assertFalse(c.flags[InvalidOperation])
2619
2620 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2621 self.assertEqual(D(-1).next_minus(context=xc), -2)
2622 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2623 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2624 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2625 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2626 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2627 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2628
2629 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2630 xc.clear_flags()
2631 self.assertRaises(InvalidOperation,
2632 D("0").compare_signal, D('nan'), context=xc)
2633 self.assertTrue(xc.flags[InvalidOperation])
2634 self.assertFalse(c.flags[InvalidOperation])
2635 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2636 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2637 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2638 D('-0.3'))
2639 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2640 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2641 D('0.0'))
2642 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2643 xc.clear_flags()
2644 self.assertRaises(InvalidOperation,
2645 D("0.2").quantize, D('1e10'), context=xc)
2646 self.assertTrue(xc.flags[InvalidOperation])
2647 self.assertFalse(c.flags[InvalidOperation])
2648 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2649 D('-0.5'))
2650
2651 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2652 D('7E+1'))
2653
2654 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2655 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2656 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2657 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2658 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2659 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2660 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2661 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2662
2663 self.assertFalse(D("0.01").is_normal(context=xc))
2664 self.assertTrue(D("0.01").is_subnormal(context=xc))
2665
2666 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2667 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2668 self.assertRaises(TypeError, D(1).radix, context=xc)
2669
2670 self.assertEqual(D(-111).logb(context=xc), 2)
2671 self.assertEqual(D(0).logical_invert(context=xc), 1)
2672 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2673 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2674
2675 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2676 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2677 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2678 self.assertEqual(D('23').rotate(1, context=xc), 3)
2679 self.assertEqual(D('23').rotate(1, context=xc), 3)
2680 xc.clear_flags()
2681 self.assertRaises(Overflow,
2682 D('23').scaleb, 1, context=xc)
2683 self.assertTrue(xc.flags[Overflow])
2684 self.assertFalse(c.flags[Overflow])
2685 self.assertEqual(D('23').shift(-1, context=xc), 0)
2686
2687 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2688 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2689
Stefan Krah040e3112012-12-15 22:33:33 +01002690 self.assertEqual(D(1).canonical(), 1)
2691 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2692 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2693 self.assertRaises(TypeError, D(1).canonical, context="x")
2694 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002695
Stefan Krahb6405ef2012-03-23 14:46:48 +01002696 def test_exception_hierarchy(self):
2697
2698 decimal = self.decimal
2699 DecimalException = decimal.DecimalException
2700 InvalidOperation = decimal.InvalidOperation
2701 FloatOperation = decimal.FloatOperation
2702 DivisionByZero = decimal.DivisionByZero
2703 Overflow = decimal.Overflow
2704 Underflow = decimal.Underflow
2705 Subnormal = decimal.Subnormal
2706 Inexact = decimal.Inexact
2707 Rounded = decimal.Rounded
2708 Clamped = decimal.Clamped
2709
2710 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2711
2712 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2713 self.assertTrue(issubclass(FloatOperation, DecimalException))
2714 self.assertTrue(issubclass(FloatOperation, TypeError))
2715 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2716 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2717 self.assertTrue(issubclass(Overflow, Rounded))
2718 self.assertTrue(issubclass(Overflow, Inexact))
2719 self.assertTrue(issubclass(Overflow, DecimalException))
2720 self.assertTrue(issubclass(Underflow, Inexact))
2721 self.assertTrue(issubclass(Underflow, Rounded))
2722 self.assertTrue(issubclass(Underflow, Subnormal))
2723 self.assertTrue(issubclass(Underflow, DecimalException))
2724
2725 self.assertTrue(issubclass(Subnormal, DecimalException))
2726 self.assertTrue(issubclass(Inexact, DecimalException))
2727 self.assertTrue(issubclass(Rounded, DecimalException))
2728 self.assertTrue(issubclass(Clamped, DecimalException))
2729
2730 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2731 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2732 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2733 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2734 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2735
Stefan Krah1919b7e2012-03-21 18:25:23 +01002736class CPythonAPItests(PythonAPItests):
2737 decimal = C
2738class PyPythonAPItests(PythonAPItests):
2739 decimal = P
2740
2741class ContextAPItests(unittest.TestCase):
2742
Stefan Krah9a4ff432012-12-16 21:10:35 +01002743 def test_none_args(self):
2744 Context = self.decimal.Context
2745 InvalidOperation = self.decimal.InvalidOperation
2746 DivisionByZero = self.decimal.DivisionByZero
2747 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002748
2749 c1 = Context()
2750 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2751 capitals=None, clamp=None, flags=None, traps=None)
2752 for c in [c1, c2]:
2753 self.assertEqual(c.prec, 28)
2754 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2755 self.assertEqual(c.Emax, 999999)
2756 self.assertEqual(c.Emin, -999999)
2757 self.assertEqual(c.capitals, 1)
2758 self.assertEqual(c.clamp, 0)
2759 assert_signals(self, c, 'flags', [])
2760 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2761 Overflow])
2762
Stefan Krah59a4a932013-01-16 12:58:59 +01002763 @cpython_only
2764 def test_from_legacy_strings(self):
2765 import _testcapi
2766 c = self.decimal.Context()
2767
2768 for rnd in RoundingModes:
2769 c.rounding = _testcapi.unicode_legacy_string(rnd)
2770 self.assertEqual(c.rounding, rnd)
2771
2772 s = _testcapi.unicode_legacy_string('')
2773 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2774
2775 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2776 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2777
Stefan Krah1919b7e2012-03-21 18:25:23 +01002778 def test_pickle(self):
2779
2780 Context = self.decimal.Context
2781
2782 savedecimal = sys.modules['decimal']
2783
2784 # Round trip
2785 sys.modules['decimal'] = self.decimal
2786 c = Context()
2787 e = pickle.loads(pickle.dumps(c))
2788
2789 self.assertEqual(c.prec, e.prec)
2790 self.assertEqual(c.Emin, e.Emin)
2791 self.assertEqual(c.Emax, e.Emax)
2792 self.assertEqual(c.rounding, e.rounding)
2793 self.assertEqual(c.capitals, e.capitals)
2794 self.assertEqual(c.clamp, e.clamp)
2795 self.assertEqual(c.flags, e.flags)
2796 self.assertEqual(c.traps, e.traps)
2797
2798 # Test interchangeability
2799 combinations = [(C, P), (P, C)] if C else [(P, P)]
2800 for dumper, loader in combinations:
Stefan Krah59a4a932013-01-16 12:58:59 +01002801 for ri, _ in enumerate(RoundingModes):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002802 for fi, _ in enumerate(OrderedSignals[dumper]):
2803 for ti, _ in enumerate(OrderedSignals[dumper]):
2804
2805 prec = random.randrange(1, 100)
2806 emin = random.randrange(-100, 0)
2807 emax = random.randrange(1, 100)
2808 caps = random.randrange(2)
2809 clamp = random.randrange(2)
2810
2811 # One module dumps
2812 sys.modules['decimal'] = dumper
2813 c = dumper.Context(
2814 prec=prec, Emin=emin, Emax=emax,
Stefan Krah59a4a932013-01-16 12:58:59 +01002815 rounding=RoundingModes[ri],
Stefan Krah1919b7e2012-03-21 18:25:23 +01002816 capitals=caps, clamp=clamp,
2817 flags=OrderedSignals[dumper][:fi],
2818 traps=OrderedSignals[dumper][:ti]
2819 )
2820 s = pickle.dumps(c)
2821
2822 # The other module loads
2823 sys.modules['decimal'] = loader
2824 d = pickle.loads(s)
2825 self.assertIsInstance(d, loader.Context)
2826
2827 self.assertEqual(d.prec, prec)
2828 self.assertEqual(d.Emin, emin)
2829 self.assertEqual(d.Emax, emax)
Stefan Krah59a4a932013-01-16 12:58:59 +01002830 self.assertEqual(d.rounding, RoundingModes[ri])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002831 self.assertEqual(d.capitals, caps)
2832 self.assertEqual(d.clamp, clamp)
2833 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2834 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2835
2836 sys.modules['decimal'] = savedecimal
2837
2838 def test_equality_with_other_types(self):
2839 Decimal = self.decimal.Decimal
2840
2841 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2842 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2843
2844 def test_copy(self):
2845 # All copies should be deep
2846 Decimal = self.decimal.Decimal
2847 Context = self.decimal.Context
2848
2849 c = Context()
2850 d = c.copy()
2851 self.assertNotEqual(id(c), id(d))
2852 self.assertNotEqual(id(c.flags), id(d.flags))
2853 self.assertNotEqual(id(c.traps), id(d.traps))
2854 k1 = set(c.flags.keys())
2855 k2 = set(d.flags.keys())
2856 self.assertEqual(k1, k2)
2857 self.assertEqual(c.flags, d.flags)
2858
2859 def test__clamp(self):
2860 # In Python 3.2, the private attribute `_clamp` was made
2861 # public (issue 8540), with the old `_clamp` becoming a
2862 # property wrapping `clamp`. For the duration of Python 3.2
2863 # only, the attribute should be gettable/settable via both
2864 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2865 # removed.
2866 Context = self.decimal.Context
2867 c = Context()
2868 self.assertRaises(AttributeError, getattr, c, '_clamp')
2869
2870 def test_abs(self):
2871 Decimal = self.decimal.Decimal
2872 Context = self.decimal.Context
2873
2874 c = Context()
2875 d = c.abs(Decimal(-1))
2876 self.assertEqual(c.abs(-1), d)
2877 self.assertRaises(TypeError, c.abs, '-1')
2878
2879 def test_add(self):
2880 Decimal = self.decimal.Decimal
2881 Context = self.decimal.Context
2882
2883 c = Context()
2884 d = c.add(Decimal(1), Decimal(1))
2885 self.assertEqual(c.add(1, 1), d)
2886 self.assertEqual(c.add(Decimal(1), 1), d)
2887 self.assertEqual(c.add(1, Decimal(1)), d)
2888 self.assertRaises(TypeError, c.add, '1', 1)
2889 self.assertRaises(TypeError, c.add, 1, '1')
2890
2891 def test_compare(self):
2892 Decimal = self.decimal.Decimal
2893 Context = self.decimal.Context
2894
2895 c = Context()
2896 d = c.compare(Decimal(1), Decimal(1))
2897 self.assertEqual(c.compare(1, 1), d)
2898 self.assertEqual(c.compare(Decimal(1), 1), d)
2899 self.assertEqual(c.compare(1, Decimal(1)), d)
2900 self.assertRaises(TypeError, c.compare, '1', 1)
2901 self.assertRaises(TypeError, c.compare, 1, '1')
2902
2903 def test_compare_signal(self):
2904 Decimal = self.decimal.Decimal
2905 Context = self.decimal.Context
2906
2907 c = Context()
2908 d = c.compare_signal(Decimal(1), Decimal(1))
2909 self.assertEqual(c.compare_signal(1, 1), d)
2910 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2911 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2912 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2913 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2914
2915 def test_compare_total(self):
2916 Decimal = self.decimal.Decimal
2917 Context = self.decimal.Context
2918
2919 c = Context()
2920 d = c.compare_total(Decimal(1), Decimal(1))
2921 self.assertEqual(c.compare_total(1, 1), d)
2922 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2923 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2924 self.assertRaises(TypeError, c.compare_total, '1', 1)
2925 self.assertRaises(TypeError, c.compare_total, 1, '1')
2926
2927 def test_compare_total_mag(self):
2928 Decimal = self.decimal.Decimal
2929 Context = self.decimal.Context
2930
2931 c = Context()
2932 d = c.compare_total_mag(Decimal(1), Decimal(1))
2933 self.assertEqual(c.compare_total_mag(1, 1), d)
2934 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2935 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2936 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2937 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2938
2939 def test_copy_abs(self):
2940 Decimal = self.decimal.Decimal
2941 Context = self.decimal.Context
2942
2943 c = Context()
2944 d = c.copy_abs(Decimal(-1))
2945 self.assertEqual(c.copy_abs(-1), d)
2946 self.assertRaises(TypeError, c.copy_abs, '-1')
2947
2948 def test_copy_decimal(self):
2949 Decimal = self.decimal.Decimal
2950 Context = self.decimal.Context
2951
2952 c = Context()
2953 d = c.copy_decimal(Decimal(-1))
2954 self.assertEqual(c.copy_decimal(-1), d)
2955 self.assertRaises(TypeError, c.copy_decimal, '-1')
2956
2957 def test_copy_negate(self):
2958 Decimal = self.decimal.Decimal
2959 Context = self.decimal.Context
2960
2961 c = Context()
2962 d = c.copy_negate(Decimal(-1))
2963 self.assertEqual(c.copy_negate(-1), d)
2964 self.assertRaises(TypeError, c.copy_negate, '-1')
2965
2966 def test_copy_sign(self):
2967 Decimal = self.decimal.Decimal
2968 Context = self.decimal.Context
2969
2970 c = Context()
2971 d = c.copy_sign(Decimal(1), Decimal(-2))
2972 self.assertEqual(c.copy_sign(1, -2), d)
2973 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2974 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2975 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2976 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2977
2978 def test_divide(self):
2979 Decimal = self.decimal.Decimal
2980 Context = self.decimal.Context
2981
2982 c = Context()
2983 d = c.divide(Decimal(1), Decimal(2))
2984 self.assertEqual(c.divide(1, 2), d)
2985 self.assertEqual(c.divide(Decimal(1), 2), d)
2986 self.assertEqual(c.divide(1, Decimal(2)), d)
2987 self.assertRaises(TypeError, c.divide, '1', 2)
2988 self.assertRaises(TypeError, c.divide, 1, '2')
2989
2990 def test_divide_int(self):
2991 Decimal = self.decimal.Decimal
2992 Context = self.decimal.Context
2993
2994 c = Context()
2995 d = c.divide_int(Decimal(1), Decimal(2))
2996 self.assertEqual(c.divide_int(1, 2), d)
2997 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2998 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2999 self.assertRaises(TypeError, c.divide_int, '1', 2)
3000 self.assertRaises(TypeError, c.divide_int, 1, '2')
3001
3002 def test_divmod(self):
3003 Decimal = self.decimal.Decimal
3004 Context = self.decimal.Context
3005
3006 c = Context()
3007 d = c.divmod(Decimal(1), Decimal(2))
3008 self.assertEqual(c.divmod(1, 2), d)
3009 self.assertEqual(c.divmod(Decimal(1), 2), d)
3010 self.assertEqual(c.divmod(1, Decimal(2)), d)
3011 self.assertRaises(TypeError, c.divmod, '1', 2)
3012 self.assertRaises(TypeError, c.divmod, 1, '2')
3013
3014 def test_exp(self):
3015 Decimal = self.decimal.Decimal
3016 Context = self.decimal.Context
3017
3018 c = Context()
3019 d = c.exp(Decimal(10))
3020 self.assertEqual(c.exp(10), d)
3021 self.assertRaises(TypeError, c.exp, '10')
3022
3023 def test_fma(self):
3024 Decimal = self.decimal.Decimal
3025 Context = self.decimal.Context
3026
3027 c = Context()
3028 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3029 self.assertEqual(c.fma(2, 3, 4), d)
3030 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3031 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3032 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3033 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3034 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3035 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3036 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3037
3038 # Issue 12079 for Context.fma ...
3039 self.assertRaises(TypeError, c.fma,
3040 Decimal('Infinity'), Decimal(0), "not a decimal")
3041 self.assertRaises(TypeError, c.fma,
3042 Decimal(1), Decimal('snan'), 1.222)
3043 # ... and for Decimal.fma.
3044 self.assertRaises(TypeError, Decimal('Infinity').fma,
3045 Decimal(0), "not a decimal")
3046 self.assertRaises(TypeError, Decimal(1).fma,
3047 Decimal('snan'), 1.222)
3048
3049 def test_is_finite(self):
3050 Decimal = self.decimal.Decimal
3051 Context = self.decimal.Context
3052
3053 c = Context()
3054 d = c.is_finite(Decimal(10))
3055 self.assertEqual(c.is_finite(10), d)
3056 self.assertRaises(TypeError, c.is_finite, '10')
3057
3058 def test_is_infinite(self):
3059 Decimal = self.decimal.Decimal
3060 Context = self.decimal.Context
3061
3062 c = Context()
3063 d = c.is_infinite(Decimal(10))
3064 self.assertEqual(c.is_infinite(10), d)
3065 self.assertRaises(TypeError, c.is_infinite, '10')
3066
3067 def test_is_nan(self):
3068 Decimal = self.decimal.Decimal
3069 Context = self.decimal.Context
3070
3071 c = Context()
3072 d = c.is_nan(Decimal(10))
3073 self.assertEqual(c.is_nan(10), d)
3074 self.assertRaises(TypeError, c.is_nan, '10')
3075
3076 def test_is_normal(self):
3077 Decimal = self.decimal.Decimal
3078 Context = self.decimal.Context
3079
3080 c = Context()
3081 d = c.is_normal(Decimal(10))
3082 self.assertEqual(c.is_normal(10), d)
3083 self.assertRaises(TypeError, c.is_normal, '10')
3084
3085 def test_is_qnan(self):
3086 Decimal = self.decimal.Decimal
3087 Context = self.decimal.Context
3088
3089 c = Context()
3090 d = c.is_qnan(Decimal(10))
3091 self.assertEqual(c.is_qnan(10), d)
3092 self.assertRaises(TypeError, c.is_qnan, '10')
3093
3094 def test_is_signed(self):
3095 Decimal = self.decimal.Decimal
3096 Context = self.decimal.Context
3097
3098 c = Context()
3099 d = c.is_signed(Decimal(10))
3100 self.assertEqual(c.is_signed(10), d)
3101 self.assertRaises(TypeError, c.is_signed, '10')
3102
3103 def test_is_snan(self):
3104 Decimal = self.decimal.Decimal
3105 Context = self.decimal.Context
3106
3107 c = Context()
3108 d = c.is_snan(Decimal(10))
3109 self.assertEqual(c.is_snan(10), d)
3110 self.assertRaises(TypeError, c.is_snan, '10')
3111
3112 def test_is_subnormal(self):
3113 Decimal = self.decimal.Decimal
3114 Context = self.decimal.Context
3115
3116 c = Context()
3117 d = c.is_subnormal(Decimal(10))
3118 self.assertEqual(c.is_subnormal(10), d)
3119 self.assertRaises(TypeError, c.is_subnormal, '10')
3120
3121 def test_is_zero(self):
3122 Decimal = self.decimal.Decimal
3123 Context = self.decimal.Context
3124
3125 c = Context()
3126 d = c.is_zero(Decimal(10))
3127 self.assertEqual(c.is_zero(10), d)
3128 self.assertRaises(TypeError, c.is_zero, '10')
3129
3130 def test_ln(self):
3131 Decimal = self.decimal.Decimal
3132 Context = self.decimal.Context
3133
3134 c = Context()
3135 d = c.ln(Decimal(10))
3136 self.assertEqual(c.ln(10), d)
3137 self.assertRaises(TypeError, c.ln, '10')
3138
3139 def test_log10(self):
3140 Decimal = self.decimal.Decimal
3141 Context = self.decimal.Context
3142
3143 c = Context()
3144 d = c.log10(Decimal(10))
3145 self.assertEqual(c.log10(10), d)
3146 self.assertRaises(TypeError, c.log10, '10')
3147
3148 def test_logb(self):
3149 Decimal = self.decimal.Decimal
3150 Context = self.decimal.Context
3151
3152 c = Context()
3153 d = c.logb(Decimal(10))
3154 self.assertEqual(c.logb(10), d)
3155 self.assertRaises(TypeError, c.logb, '10')
3156
3157 def test_logical_and(self):
3158 Decimal = self.decimal.Decimal
3159 Context = self.decimal.Context
3160
3161 c = Context()
3162 d = c.logical_and(Decimal(1), Decimal(1))
3163 self.assertEqual(c.logical_and(1, 1), d)
3164 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3165 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3166 self.assertRaises(TypeError, c.logical_and, '1', 1)
3167 self.assertRaises(TypeError, c.logical_and, 1, '1')
3168
3169 def test_logical_invert(self):
3170 Decimal = self.decimal.Decimal
3171 Context = self.decimal.Context
3172
3173 c = Context()
3174 d = c.logical_invert(Decimal(1000))
3175 self.assertEqual(c.logical_invert(1000), d)
3176 self.assertRaises(TypeError, c.logical_invert, '1000')
3177
3178 def test_logical_or(self):
3179 Decimal = self.decimal.Decimal
3180 Context = self.decimal.Context
3181
3182 c = Context()
3183 d = c.logical_or(Decimal(1), Decimal(1))
3184 self.assertEqual(c.logical_or(1, 1), d)
3185 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3186 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3187 self.assertRaises(TypeError, c.logical_or, '1', 1)
3188 self.assertRaises(TypeError, c.logical_or, 1, '1')
3189
3190 def test_logical_xor(self):
3191 Decimal = self.decimal.Decimal
3192 Context = self.decimal.Context
3193
3194 c = Context()
3195 d = c.logical_xor(Decimal(1), Decimal(1))
3196 self.assertEqual(c.logical_xor(1, 1), d)
3197 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3198 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3199 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3200 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3201
3202 def test_max(self):
3203 Decimal = self.decimal.Decimal
3204 Context = self.decimal.Context
3205
3206 c = Context()
3207 d = c.max(Decimal(1), Decimal(2))
3208 self.assertEqual(c.max(1, 2), d)
3209 self.assertEqual(c.max(Decimal(1), 2), d)
3210 self.assertEqual(c.max(1, Decimal(2)), d)
3211 self.assertRaises(TypeError, c.max, '1', 2)
3212 self.assertRaises(TypeError, c.max, 1, '2')
3213
3214 def test_max_mag(self):
3215 Decimal = self.decimal.Decimal
3216 Context = self.decimal.Context
3217
3218 c = Context()
3219 d = c.max_mag(Decimal(1), Decimal(2))
3220 self.assertEqual(c.max_mag(1, 2), d)
3221 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3222 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3223 self.assertRaises(TypeError, c.max_mag, '1', 2)
3224 self.assertRaises(TypeError, c.max_mag, 1, '2')
3225
3226 def test_min(self):
3227 Decimal = self.decimal.Decimal
3228 Context = self.decimal.Context
3229
3230 c = Context()
3231 d = c.min(Decimal(1), Decimal(2))
3232 self.assertEqual(c.min(1, 2), d)
3233 self.assertEqual(c.min(Decimal(1), 2), d)
3234 self.assertEqual(c.min(1, Decimal(2)), d)
3235 self.assertRaises(TypeError, c.min, '1', 2)
3236 self.assertRaises(TypeError, c.min, 1, '2')
3237
3238 def test_min_mag(self):
3239 Decimal = self.decimal.Decimal
3240 Context = self.decimal.Context
3241
3242 c = Context()
3243 d = c.min_mag(Decimal(1), Decimal(2))
3244 self.assertEqual(c.min_mag(1, 2), d)
3245 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3246 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3247 self.assertRaises(TypeError, c.min_mag, '1', 2)
3248 self.assertRaises(TypeError, c.min_mag, 1, '2')
3249
3250 def test_minus(self):
3251 Decimal = self.decimal.Decimal
3252 Context = self.decimal.Context
3253
3254 c = Context()
3255 d = c.minus(Decimal(10))
3256 self.assertEqual(c.minus(10), d)
3257 self.assertRaises(TypeError, c.minus, '10')
3258
3259 def test_multiply(self):
3260 Decimal = self.decimal.Decimal
3261 Context = self.decimal.Context
3262
3263 c = Context()
3264 d = c.multiply(Decimal(1), Decimal(2))
3265 self.assertEqual(c.multiply(1, 2), d)
3266 self.assertEqual(c.multiply(Decimal(1), 2), d)
3267 self.assertEqual(c.multiply(1, Decimal(2)), d)
3268 self.assertRaises(TypeError, c.multiply, '1', 2)
3269 self.assertRaises(TypeError, c.multiply, 1, '2')
3270
3271 def test_next_minus(self):
3272 Decimal = self.decimal.Decimal
3273 Context = self.decimal.Context
3274
3275 c = Context()
3276 d = c.next_minus(Decimal(10))
3277 self.assertEqual(c.next_minus(10), d)
3278 self.assertRaises(TypeError, c.next_minus, '10')
3279
3280 def test_next_plus(self):
3281 Decimal = self.decimal.Decimal
3282 Context = self.decimal.Context
3283
3284 c = Context()
3285 d = c.next_plus(Decimal(10))
3286 self.assertEqual(c.next_plus(10), d)
3287 self.assertRaises(TypeError, c.next_plus, '10')
3288
3289 def test_next_toward(self):
3290 Decimal = self.decimal.Decimal
3291 Context = self.decimal.Context
3292
3293 c = Context()
3294 d = c.next_toward(Decimal(1), Decimal(2))
3295 self.assertEqual(c.next_toward(1, 2), d)
3296 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3297 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3298 self.assertRaises(TypeError, c.next_toward, '1', 2)
3299 self.assertRaises(TypeError, c.next_toward, 1, '2')
3300
3301 def test_normalize(self):
3302 Decimal = self.decimal.Decimal
3303 Context = self.decimal.Context
3304
3305 c = Context()
3306 d = c.normalize(Decimal(10))
3307 self.assertEqual(c.normalize(10), d)
3308 self.assertRaises(TypeError, c.normalize, '10')
3309
3310 def test_number_class(self):
3311 Decimal = self.decimal.Decimal
3312 Context = self.decimal.Context
3313
3314 c = Context()
3315 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3316 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3317 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3318
3319 def test_plus(self):
3320 Decimal = self.decimal.Decimal
3321 Context = self.decimal.Context
3322
3323 c = Context()
3324 d = c.plus(Decimal(10))
3325 self.assertEqual(c.plus(10), d)
3326 self.assertRaises(TypeError, c.plus, '10')
3327
3328 def test_power(self):
3329 Decimal = self.decimal.Decimal
3330 Context = self.decimal.Context
3331
3332 c = Context()
3333 d = c.power(Decimal(1), Decimal(4))
3334 self.assertEqual(c.power(1, 4), d)
3335 self.assertEqual(c.power(Decimal(1), 4), d)
3336 self.assertEqual(c.power(1, Decimal(4)), d)
3337 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3338 self.assertRaises(TypeError, c.power, '1', 4)
3339 self.assertRaises(TypeError, c.power, 1, '4')
3340 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3341
3342 def test_quantize(self):
3343 Decimal = self.decimal.Decimal
3344 Context = self.decimal.Context
3345
3346 c = Context()
3347 d = c.quantize(Decimal(1), Decimal(2))
3348 self.assertEqual(c.quantize(1, 2), d)
3349 self.assertEqual(c.quantize(Decimal(1), 2), d)
3350 self.assertEqual(c.quantize(1, Decimal(2)), d)
3351 self.assertRaises(TypeError, c.quantize, '1', 2)
3352 self.assertRaises(TypeError, c.quantize, 1, '2')
3353
3354 def test_remainder(self):
3355 Decimal = self.decimal.Decimal
3356 Context = self.decimal.Context
3357
3358 c = Context()
3359 d = c.remainder(Decimal(1), Decimal(2))
3360 self.assertEqual(c.remainder(1, 2), d)
3361 self.assertEqual(c.remainder(Decimal(1), 2), d)
3362 self.assertEqual(c.remainder(1, Decimal(2)), d)
3363 self.assertRaises(TypeError, c.remainder, '1', 2)
3364 self.assertRaises(TypeError, c.remainder, 1, '2')
3365
3366 def test_remainder_near(self):
3367 Decimal = self.decimal.Decimal
3368 Context = self.decimal.Context
3369
3370 c = Context()
3371 d = c.remainder_near(Decimal(1), Decimal(2))
3372 self.assertEqual(c.remainder_near(1, 2), d)
3373 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3374 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3375 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3376 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3377
3378 def test_rotate(self):
3379 Decimal = self.decimal.Decimal
3380 Context = self.decimal.Context
3381
3382 c = Context()
3383 d = c.rotate(Decimal(1), Decimal(2))
3384 self.assertEqual(c.rotate(1, 2), d)
3385 self.assertEqual(c.rotate(Decimal(1), 2), d)
3386 self.assertEqual(c.rotate(1, Decimal(2)), d)
3387 self.assertRaises(TypeError, c.rotate, '1', 2)
3388 self.assertRaises(TypeError, c.rotate, 1, '2')
3389
3390 def test_sqrt(self):
3391 Decimal = self.decimal.Decimal
3392 Context = self.decimal.Context
3393
3394 c = Context()
3395 d = c.sqrt(Decimal(10))
3396 self.assertEqual(c.sqrt(10), d)
3397 self.assertRaises(TypeError, c.sqrt, '10')
3398
3399 def test_same_quantum(self):
3400 Decimal = self.decimal.Decimal
3401 Context = self.decimal.Context
3402
3403 c = Context()
3404 d = c.same_quantum(Decimal(1), Decimal(2))
3405 self.assertEqual(c.same_quantum(1, 2), d)
3406 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3407 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3408 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3409 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3410
3411 def test_scaleb(self):
3412 Decimal = self.decimal.Decimal
3413 Context = self.decimal.Context
3414
3415 c = Context()
3416 d = c.scaleb(Decimal(1), Decimal(2))
3417 self.assertEqual(c.scaleb(1, 2), d)
3418 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3419 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3420 self.assertRaises(TypeError, c.scaleb, '1', 2)
3421 self.assertRaises(TypeError, c.scaleb, 1, '2')
3422
3423 def test_shift(self):
3424 Decimal = self.decimal.Decimal
3425 Context = self.decimal.Context
3426
3427 c = Context()
3428 d = c.shift(Decimal(1), Decimal(2))
3429 self.assertEqual(c.shift(1, 2), d)
3430 self.assertEqual(c.shift(Decimal(1), 2), d)
3431 self.assertEqual(c.shift(1, Decimal(2)), d)
3432 self.assertRaises(TypeError, c.shift, '1', 2)
3433 self.assertRaises(TypeError, c.shift, 1, '2')
3434
3435 def test_subtract(self):
3436 Decimal = self.decimal.Decimal
3437 Context = self.decimal.Context
3438
3439 c = Context()
3440 d = c.subtract(Decimal(1), Decimal(2))
3441 self.assertEqual(c.subtract(1, 2), d)
3442 self.assertEqual(c.subtract(Decimal(1), 2), d)
3443 self.assertEqual(c.subtract(1, Decimal(2)), d)
3444 self.assertRaises(TypeError, c.subtract, '1', 2)
3445 self.assertRaises(TypeError, c.subtract, 1, '2')
3446
3447 def test_to_eng_string(self):
3448 Decimal = self.decimal.Decimal
3449 Context = self.decimal.Context
3450
3451 c = Context()
3452 d = c.to_eng_string(Decimal(10))
3453 self.assertEqual(c.to_eng_string(10), d)
3454 self.assertRaises(TypeError, c.to_eng_string, '10')
3455
3456 def test_to_sci_string(self):
3457 Decimal = self.decimal.Decimal
3458 Context = self.decimal.Context
3459
3460 c = Context()
3461 d = c.to_sci_string(Decimal(10))
3462 self.assertEqual(c.to_sci_string(10), d)
3463 self.assertRaises(TypeError, c.to_sci_string, '10')
3464
3465 def test_to_integral_exact(self):
3466 Decimal = self.decimal.Decimal
3467 Context = self.decimal.Context
3468
3469 c = Context()
3470 d = c.to_integral_exact(Decimal(10))
3471 self.assertEqual(c.to_integral_exact(10), d)
3472 self.assertRaises(TypeError, c.to_integral_exact, '10')
3473
3474 def test_to_integral_value(self):
3475 Decimal = self.decimal.Decimal
3476 Context = self.decimal.Context
3477
3478 c = Context()
3479 d = c.to_integral_value(Decimal(10))
3480 self.assertEqual(c.to_integral_value(10), d)
3481 self.assertRaises(TypeError, c.to_integral_value, '10')
3482 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3483
3484class CContextAPItests(ContextAPItests):
3485 decimal = C
3486class PyContextAPItests(ContextAPItests):
3487 decimal = P
3488
3489class ContextWithStatement(unittest.TestCase):
3490 # Can't do these as docstrings until Python 2.6
3491 # as doctest can't handle __future__ statements
3492
3493 def test_localcontext(self):
3494 # Use a copy of the current context in the block
3495 getcontext = self.decimal.getcontext
3496 localcontext = self.decimal.localcontext
3497
3498 orig_ctx = getcontext()
3499 with localcontext() as enter_ctx:
3500 set_ctx = getcontext()
3501 final_ctx = getcontext()
3502 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3503 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3504 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3505
3506 def test_localcontextarg(self):
3507 # Use a copy of the supplied context in the block
3508 Context = self.decimal.Context
3509 getcontext = self.decimal.getcontext
3510 localcontext = self.decimal.localcontext
3511
3512 localcontext = self.decimal.localcontext
3513 orig_ctx = getcontext()
3514 new_ctx = Context(prec=42)
3515 with localcontext(new_ctx) as enter_ctx:
3516 set_ctx = getcontext()
3517 final_ctx = getcontext()
3518 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3519 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3520 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3521 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3522
3523 def test_nested_with_statements(self):
3524 # Use a copy of the supplied context in the block
3525 Decimal = self.decimal.Decimal
3526 Context = self.decimal.Context
3527 getcontext = self.decimal.getcontext
3528 localcontext = self.decimal.localcontext
3529 Clamped = self.decimal.Clamped
3530 Overflow = self.decimal.Overflow
3531
3532 orig_ctx = getcontext()
3533 orig_ctx.clear_flags()
3534 new_ctx = Context(Emax=384)
3535 with localcontext() as c1:
3536 self.assertEqual(c1.flags, orig_ctx.flags)
3537 self.assertEqual(c1.traps, orig_ctx.traps)
3538 c1.traps[Clamped] = True
3539 c1.Emin = -383
3540 self.assertNotEqual(orig_ctx.Emin, -383)
3541 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3542 self.assertTrue(c1.flags[Clamped])
3543 with localcontext(new_ctx) as c2:
3544 self.assertEqual(c2.flags, new_ctx.flags)
3545 self.assertEqual(c2.traps, new_ctx.traps)
3546 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3547 self.assertFalse(c2.flags[Clamped])
3548 self.assertTrue(c2.flags[Overflow])
3549 del c2
3550 self.assertFalse(c1.flags[Overflow])
3551 del c1
3552 self.assertNotEqual(orig_ctx.Emin, -383)
3553 self.assertFalse(orig_ctx.flags[Clamped])
3554 self.assertFalse(orig_ctx.flags[Overflow])
3555 self.assertFalse(new_ctx.flags[Clamped])
3556 self.assertFalse(new_ctx.flags[Overflow])
3557
3558 def test_with_statements_gc1(self):
3559 localcontext = self.decimal.localcontext
3560
3561 with localcontext() as c1:
3562 del c1
3563 with localcontext() as c2:
3564 del c2
3565 with localcontext() as c3:
3566 del c3
3567 with localcontext() as c4:
3568 del c4
3569
3570 def test_with_statements_gc2(self):
3571 localcontext = self.decimal.localcontext
3572
3573 with localcontext() as c1:
3574 with localcontext(c1) as c2:
3575 del c1
3576 with localcontext(c2) as c3:
3577 del c2
3578 with localcontext(c3) as c4:
3579 del c3
3580 del c4
3581
3582 def test_with_statements_gc3(self):
3583 Context = self.decimal.Context
3584 localcontext = self.decimal.localcontext
3585 getcontext = self.decimal.getcontext
3586 setcontext = self.decimal.setcontext
3587
3588 with localcontext() as c1:
3589 del c1
3590 n1 = Context(prec=1)
3591 setcontext(n1)
3592 with localcontext(n1) as c2:
3593 del n1
3594 self.assertEqual(c2.prec, 1)
3595 del c2
3596 n2 = Context(prec=2)
3597 setcontext(n2)
3598 del n2
3599 self.assertEqual(getcontext().prec, 2)
3600 n3 = Context(prec=3)
3601 setcontext(n3)
3602 self.assertEqual(getcontext().prec, 3)
3603 with localcontext(n3) as c3:
3604 del n3
3605 self.assertEqual(c3.prec, 3)
3606 del c3
3607 n4 = Context(prec=4)
3608 setcontext(n4)
3609 del n4
3610 self.assertEqual(getcontext().prec, 4)
3611 with localcontext() as c4:
3612 self.assertEqual(c4.prec, 4)
3613 del c4
3614
3615class CContextWithStatement(ContextWithStatement):
3616 decimal = C
3617class PyContextWithStatement(ContextWithStatement):
3618 decimal = P
3619
3620class ContextFlags(unittest.TestCase):
3621
3622 def test_flags_irrelevant(self):
3623 # check that the result (numeric result + flags raised) of an
3624 # arithmetic operation doesn't depend on the current flags
3625 Decimal = self.decimal.Decimal
3626 Context = self.decimal.Context
3627 Inexact = self.decimal.Inexact
3628 Rounded = self.decimal.Rounded
3629 Underflow = self.decimal.Underflow
3630 Clamped = self.decimal.Clamped
3631 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003632
3633 def raise_error(context, flag):
3634 if self.decimal == C:
3635 context.flags[flag] = True
3636 if context.traps[flag]:
3637 raise flag
3638 else:
3639 context._raise_error(flag)
3640
3641 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3642 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3643
3644 # operations that raise various flags, in the form (function, arglist)
3645 operations = [
3646 (context._apply, [Decimal("100E-425000010")]),
3647 (context.sqrt, [Decimal(2)]),
3648 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3649 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3650 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3651 ]
3652
3653 # try various flags individually, then a whole lot at once
3654 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3655 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3656
3657 for fn, args in operations:
3658 # find answer and flags raised using a clean context
3659 context.clear_flags()
3660 ans = fn(*args)
3661 flags = [k for k, v in context.flags.items() if v]
3662
3663 for extra_flags in flagsets:
3664 # set flags, before calling operation
3665 context.clear_flags()
3666 for flag in extra_flags:
3667 raise_error(context, flag)
3668 new_ans = fn(*args)
3669
3670 # flags that we expect to be set after the operation
3671 expected_flags = list(flags)
3672 for flag in extra_flags:
3673 if flag not in expected_flags:
3674 expected_flags.append(flag)
3675 expected_flags.sort(key=id)
3676
3677 # flags we actually got
3678 new_flags = [k for k,v in context.flags.items() if v]
3679 new_flags.sort(key=id)
3680
3681 self.assertEqual(ans, new_ans,
3682 "operation produces different answers depending on flags set: " +
3683 "expected %s, got %s." % (ans, new_ans))
3684 self.assertEqual(new_flags, expected_flags,
3685 "operation raises different flags depending on flags set: " +
3686 "expected %s, got %s" % (expected_flags, new_flags))
3687
3688 def test_flag_comparisons(self):
3689 Context = self.decimal.Context
3690 Inexact = self.decimal.Inexact
3691 Rounded = self.decimal.Rounded
3692
3693 c = Context()
3694
3695 # Valid SignalDict
3696 self.assertNotEqual(c.flags, c.traps)
3697 self.assertNotEqual(c.traps, c.flags)
3698
3699 c.flags = c.traps
3700 self.assertEqual(c.flags, c.traps)
3701 self.assertEqual(c.traps, c.flags)
3702
3703 c.flags[Rounded] = True
3704 c.traps = c.flags
3705 self.assertEqual(c.flags, c.traps)
3706 self.assertEqual(c.traps, c.flags)
3707
3708 d = {}
3709 d.update(c.flags)
3710 self.assertEqual(d, c.flags)
3711 self.assertEqual(c.flags, d)
3712
3713 d[Inexact] = True
3714 self.assertNotEqual(d, c.flags)
3715 self.assertNotEqual(c.flags, d)
3716
3717 # Invalid SignalDict
3718 d = {Inexact:False}
3719 self.assertNotEqual(d, c.flags)
3720 self.assertNotEqual(c.flags, d)
3721
3722 d = ["xyz"]
3723 self.assertNotEqual(d, c.flags)
3724 self.assertNotEqual(c.flags, d)
3725
3726 @requires_IEEE_754
3727 def test_float_operation(self):
3728 Decimal = self.decimal.Decimal
3729 FloatOperation = self.decimal.FloatOperation
3730 localcontext = self.decimal.localcontext
3731
3732 with localcontext() as c:
3733 ##### trap is off by default
3734 self.assertFalse(c.traps[FloatOperation])
3735
3736 # implicit conversion sets the flag
3737 c.clear_flags()
3738 self.assertEqual(Decimal(7.5), 7.5)
3739 self.assertTrue(c.flags[FloatOperation])
3740
3741 c.clear_flags()
3742 self.assertEqual(c.create_decimal(7.5), 7.5)
3743 self.assertTrue(c.flags[FloatOperation])
3744
3745 # explicit conversion does not set the flag
3746 c.clear_flags()
3747 x = Decimal.from_float(7.5)
3748 self.assertFalse(c.flags[FloatOperation])
3749 # comparison sets the flag
3750 self.assertEqual(x, 7.5)
3751 self.assertTrue(c.flags[FloatOperation])
3752
3753 c.clear_flags()
3754 x = c.create_decimal_from_float(7.5)
3755 self.assertFalse(c.flags[FloatOperation])
3756 self.assertEqual(x, 7.5)
3757 self.assertTrue(c.flags[FloatOperation])
3758
3759 ##### set the trap
3760 c.traps[FloatOperation] = True
3761
3762 # implicit conversion raises
3763 c.clear_flags()
3764 self.assertRaises(FloatOperation, Decimal, 7.5)
3765 self.assertTrue(c.flags[FloatOperation])
3766
3767 c.clear_flags()
3768 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3769 self.assertTrue(c.flags[FloatOperation])
3770
3771 # explicit conversion is silent
3772 c.clear_flags()
3773 x = Decimal.from_float(7.5)
3774 self.assertFalse(c.flags[FloatOperation])
3775
3776 c.clear_flags()
3777 x = c.create_decimal_from_float(7.5)
3778 self.assertFalse(c.flags[FloatOperation])
3779
3780 def test_float_comparison(self):
3781 Decimal = self.decimal.Decimal
3782 Context = self.decimal.Context
3783 FloatOperation = self.decimal.FloatOperation
3784 localcontext = self.decimal.localcontext
3785
3786 def assert_attr(a, b, attr, context, signal=None):
3787 context.clear_flags()
3788 f = getattr(a, attr)
3789 if signal == FloatOperation:
3790 self.assertRaises(signal, f, b)
3791 else:
3792 self.assertIs(f(b), True)
3793 self.assertTrue(context.flags[FloatOperation])
3794
3795 small_d = Decimal('0.25')
3796 big_d = Decimal('3.0')
3797 small_f = 0.25
3798 big_f = 3.0
3799
3800 zero_d = Decimal('0.0')
3801 neg_zero_d = Decimal('-0.0')
3802 zero_f = 0.0
3803 neg_zero_f = -0.0
3804
3805 inf_d = Decimal('Infinity')
3806 neg_inf_d = Decimal('-Infinity')
3807 inf_f = float('inf')
3808 neg_inf_f = float('-inf')
3809
3810 def doit(c, signal=None):
3811 # Order
3812 for attr in '__lt__', '__le__':
3813 assert_attr(small_d, big_f, attr, c, signal)
3814
3815 for attr in '__gt__', '__ge__':
3816 assert_attr(big_d, small_f, attr, c, signal)
3817
3818 # Equality
3819 assert_attr(small_d, small_f, '__eq__', c, None)
3820
3821 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3822 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3823
3824 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3825 assert_attr(zero_d, zero_f, '__eq__', c, None)
3826
3827 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3828 assert_attr(inf_d, inf_f, '__eq__', c, None)
3829
3830 # Inequality
3831 assert_attr(small_d, big_f, '__ne__', c, None)
3832
3833 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3834
3835 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3836 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3837
3838 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3839
3840 def test_containers(c, signal=None):
3841 c.clear_flags()
3842 s = set([100.0, Decimal('100.0')])
3843 self.assertEqual(len(s), 1)
3844 self.assertTrue(c.flags[FloatOperation])
3845
3846 c.clear_flags()
3847 if signal:
3848 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3849 else:
3850 s = sorted([10.0, Decimal('10.0')])
3851 self.assertTrue(c.flags[FloatOperation])
3852
3853 c.clear_flags()
3854 b = 10.0 in [Decimal('10.0'), 1.0]
3855 self.assertTrue(c.flags[FloatOperation])
3856
3857 c.clear_flags()
3858 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3859 self.assertTrue(c.flags[FloatOperation])
3860
3861 nc = Context()
3862 with localcontext(nc) as c:
3863 self.assertFalse(c.traps[FloatOperation])
3864 doit(c, signal=None)
3865 test_containers(c, signal=None)
3866
3867 c.traps[FloatOperation] = True
3868 doit(c, signal=FloatOperation)
3869 test_containers(c, signal=FloatOperation)
3870
3871 def test_float_operation_default(self):
3872 Decimal = self.decimal.Decimal
3873 Context = self.decimal.Context
3874 Inexact = self.decimal.Inexact
3875 FloatOperation= self.decimal.FloatOperation
3876
3877 context = Context()
3878 self.assertFalse(context.flags[FloatOperation])
3879 self.assertFalse(context.traps[FloatOperation])
3880
3881 context.clear_traps()
3882 context.traps[Inexact] = True
3883 context.traps[FloatOperation] = True
3884 self.assertTrue(context.traps[FloatOperation])
3885 self.assertTrue(context.traps[Inexact])
3886
3887class CContextFlags(ContextFlags):
3888 decimal = C
3889class PyContextFlags(ContextFlags):
3890 decimal = P
3891
3892class SpecialContexts(unittest.TestCase):
3893 """Test the context templates."""
3894
3895 def test_context_templates(self):
3896 BasicContext = self.decimal.BasicContext
3897 ExtendedContext = self.decimal.ExtendedContext
3898 getcontext = self.decimal.getcontext
3899 setcontext = self.decimal.setcontext
3900 InvalidOperation = self.decimal.InvalidOperation
3901 DivisionByZero = self.decimal.DivisionByZero
3902 Overflow = self.decimal.Overflow
3903 Underflow = self.decimal.Underflow
3904 Clamped = self.decimal.Clamped
3905
3906 assert_signals(self, BasicContext, 'traps',
3907 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3908 )
3909
3910 savecontext = getcontext().copy()
3911 basic_context_prec = BasicContext.prec
3912 extended_context_prec = ExtendedContext.prec
3913
3914 ex = None
3915 try:
3916 BasicContext.prec = ExtendedContext.prec = 441
3917 for template in BasicContext, ExtendedContext:
3918 setcontext(template)
3919 c = getcontext()
3920 self.assertIsNot(c, template)
3921 self.assertEqual(c.prec, 441)
3922 except Exception as e:
3923 ex = e.__class__
3924 finally:
3925 BasicContext.prec = basic_context_prec
3926 ExtendedContext.prec = extended_context_prec
3927 setcontext(savecontext)
3928 if ex:
3929 raise ex
3930
3931 def test_default_context(self):
3932 DefaultContext = self.decimal.DefaultContext
3933 BasicContext = self.decimal.BasicContext
3934 ExtendedContext = self.decimal.ExtendedContext
3935 getcontext = self.decimal.getcontext
3936 setcontext = self.decimal.setcontext
3937 InvalidOperation = self.decimal.InvalidOperation
3938 DivisionByZero = self.decimal.DivisionByZero
3939 Overflow = self.decimal.Overflow
3940
3941 self.assertEqual(BasicContext.prec, 9)
3942 self.assertEqual(ExtendedContext.prec, 9)
3943
3944 assert_signals(self, DefaultContext, 'traps',
3945 [InvalidOperation, DivisionByZero, Overflow]
3946 )
3947
3948 savecontext = getcontext().copy()
3949 default_context_prec = DefaultContext.prec
3950
3951 ex = None
3952 try:
3953 c = getcontext()
3954 saveprec = c.prec
3955
3956 DefaultContext.prec = 961
3957 c = getcontext()
3958 self.assertEqual(c.prec, saveprec)
3959
3960 setcontext(DefaultContext)
3961 c = getcontext()
3962 self.assertIsNot(c, DefaultContext)
3963 self.assertEqual(c.prec, 961)
3964 except Exception as e:
3965 ex = e.__class__
3966 finally:
3967 DefaultContext.prec = default_context_prec
3968 setcontext(savecontext)
3969 if ex:
3970 raise ex
3971
3972class CSpecialContexts(SpecialContexts):
3973 decimal = C
3974class PySpecialContexts(SpecialContexts):
3975 decimal = P
3976
3977class ContextInputValidation(unittest.TestCase):
3978
3979 def test_invalid_context(self):
3980 Context = self.decimal.Context
3981 DefaultContext = self.decimal.DefaultContext
3982
3983 c = DefaultContext.copy()
3984
3985 # prec, Emax
3986 for attr in ['prec', 'Emax']:
3987 setattr(c, attr, 999999)
3988 self.assertEqual(getattr(c, attr), 999999)
3989 self.assertRaises(ValueError, setattr, c, attr, -1)
3990 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3991
3992 # Emin
3993 setattr(c, 'Emin', -999999)
3994 self.assertEqual(getattr(c, 'Emin'), -999999)
3995 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3996 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3997
Stefan Krah1919b7e2012-03-21 18:25:23 +01003998 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3999 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
4000 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
4001 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
4002
4003 # capitals, clamp
4004 for attr in ['capitals', 'clamp']:
4005 self.assertRaises(ValueError, setattr, c, attr, -1)
4006 self.assertRaises(ValueError, setattr, c, attr, 2)
4007 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4008
4009 # Invalid attribute
4010 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4011
4012 # Invalid signal dict
4013 self.assertRaises(TypeError, setattr, c, 'flags', [])
4014 self.assertRaises(KeyError, setattr, c, 'flags', {})
4015 self.assertRaises(KeyError, setattr, c, 'traps',
4016 {'InvalidOperation':0})
4017
4018 # Attributes cannot be deleted
4019 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4020 'flags', 'traps']:
4021 self.assertRaises(AttributeError, c.__delattr__, attr)
4022
4023 # Invalid attributes
4024 self.assertRaises(TypeError, getattr, c, 9)
4025 self.assertRaises(TypeError, setattr, c, 9)
4026
4027 # Invalid values in constructor
4028 self.assertRaises(TypeError, Context, rounding=999999)
4029 self.assertRaises(TypeError, Context, rounding='xyz')
4030 self.assertRaises(ValueError, Context, clamp=2)
4031 self.assertRaises(ValueError, Context, capitals=-1)
4032 self.assertRaises(KeyError, Context, flags=["P"])
4033 self.assertRaises(KeyError, Context, traps=["Q"])
4034
4035 # Type error in conversion
4036 self.assertRaises(TypeError, Context, flags=(0,1))
4037 self.assertRaises(TypeError, Context, traps=(1,0))
4038
4039class CContextInputValidation(ContextInputValidation):
4040 decimal = C
4041class PyContextInputValidation(ContextInputValidation):
4042 decimal = P
4043
4044class ContextSubclassing(unittest.TestCase):
4045
4046 def test_context_subclassing(self):
4047 decimal = self.decimal
4048 Decimal = decimal.Decimal
4049 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004050 Clamped = decimal.Clamped
4051 DivisionByZero = decimal.DivisionByZero
4052 Inexact = decimal.Inexact
4053 Overflow = decimal.Overflow
4054 Rounded = decimal.Rounded
4055 Subnormal = decimal.Subnormal
4056 Underflow = decimal.Underflow
4057 InvalidOperation = decimal.InvalidOperation
4058
4059 class MyContext(Context):
4060 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4061 capitals=None, clamp=None, flags=None,
4062 traps=None):
4063 Context.__init__(self)
4064 if prec is not None:
4065 self.prec = prec
4066 if rounding is not None:
4067 self.rounding = rounding
4068 if Emin is not None:
4069 self.Emin = Emin
4070 if Emax is not None:
4071 self.Emax = Emax
4072 if capitals is not None:
4073 self.capitals = capitals
4074 if clamp is not None:
4075 self.clamp = clamp
4076 if flags is not None:
4077 if isinstance(flags, list):
4078 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4079 self.flags = flags
4080 if traps is not None:
4081 if isinstance(traps, list):
4082 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4083 self.traps = traps
4084
4085 c = Context()
4086 d = MyContext()
4087 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4088 'flags', 'traps'):
4089 self.assertEqual(getattr(c, attr), getattr(d, attr))
4090
4091 # prec
4092 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4093 c = MyContext(prec=1)
4094 self.assertEqual(c.prec, 1)
4095 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4096
4097 # rounding
4098 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4099 c = MyContext(rounding=ROUND_DOWN, prec=1)
4100 self.assertEqual(c.rounding, ROUND_DOWN)
4101 self.assertEqual(c.plus(Decimal('9.9')), 9)
4102
4103 # Emin
4104 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4105 c = MyContext(Emin=-1, prec=1)
4106 self.assertEqual(c.Emin, -1)
4107 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4108 self.assertEqual(x, Decimal('0.0'))
4109 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4110 self.assertTrue(c.flags[signal])
4111
4112 # Emax
4113 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4114 c = MyContext(Emax=1, prec=1)
4115 self.assertEqual(c.Emax, 1)
4116 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4117 if self.decimal == C:
4118 for signal in (Inexact, Overflow, Rounded):
4119 self.assertTrue(c.flags[signal])
4120
4121 # capitals
4122 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4123 c = MyContext(capitals=0)
4124 self.assertEqual(c.capitals, 0)
4125 x = c.create_decimal('1E222')
4126 self.assertEqual(c.to_sci_string(x), '1e+222')
4127
4128 # clamp
4129 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4130 c = MyContext(clamp=1, Emax=99)
4131 self.assertEqual(c.clamp, 1)
4132 x = c.plus(Decimal('1e99'))
4133 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4134
4135 # flags
4136 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4137 c = MyContext(flags=[Rounded, DivisionByZero])
4138 for signal in (Rounded, DivisionByZero):
4139 self.assertTrue(c.flags[signal])
4140 c.clear_flags()
4141 for signal in OrderedSignals[decimal]:
4142 self.assertFalse(c.flags[signal])
4143
4144 # traps
4145 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4146 c = MyContext(traps=[Rounded, DivisionByZero])
4147 for signal in (Rounded, DivisionByZero):
4148 self.assertTrue(c.traps[signal])
4149 c.clear_traps()
4150 for signal in OrderedSignals[decimal]:
4151 self.assertFalse(c.traps[signal])
4152
4153class CContextSubclassing(ContextSubclassing):
4154 decimal = C
4155class PyContextSubclassing(ContextSubclassing):
4156 decimal = P
4157
4158@skip_if_extra_functionality
4159class CheckAttributes(unittest.TestCase):
4160
4161 def test_module_attributes(self):
4162
4163 # Architecture dependent context limits
4164 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4165 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4166 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4167 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4168
4169 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4170 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4171
4172 self.assertEqual(C.__version__, P.__version__)
Stefan Krah45059eb2013-11-24 19:44:57 +01004173 self.assertEqual(C.__libmpdec_version__, P.__libmpdec_version__)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004174
4175 x = dir(C)
4176 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02004177 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004178
4179 def test_context_attributes(self):
4180
4181 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4182 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4183 self.assertEqual(set(x) - set(y), set())
4184
4185 def test_decimal_attributes(self):
4186
4187 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4188 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4189 self.assertEqual(set(x) - set(y), set())
4190
4191class Coverage(unittest.TestCase):
4192
4193 def test_adjusted(self):
4194 Decimal = self.decimal.Decimal
4195
4196 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4197 # XXX raise?
4198 self.assertEqual(Decimal('nan').adjusted(), 0)
4199 self.assertEqual(Decimal('inf').adjusted(), 0)
4200
4201 def test_canonical(self):
4202 Decimal = self.decimal.Decimal
4203 getcontext = self.decimal.getcontext
4204
4205 x = Decimal(9).canonical()
4206 self.assertEqual(x, 9)
4207
4208 c = getcontext()
4209 x = c.canonical(Decimal(9))
4210 self.assertEqual(x, 9)
4211
4212 def test_context_repr(self):
4213 c = self.decimal.DefaultContext.copy()
4214
4215 c.prec = 425000000
4216 c.Emax = 425000000
4217 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004218 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004219 c.capitals = 0
4220 c.clamp = 1
4221 for sig in OrderedSignals[self.decimal]:
4222 c.flags[sig] = False
4223 c.traps[sig] = False
4224
4225 s = c.__repr__()
4226 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4227 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4228 "flags=[], traps=[])"
4229 self.assertEqual(s, t)
4230
4231 def test_implicit_context(self):
4232 Decimal = self.decimal.Decimal
4233 localcontext = self.decimal.localcontext
4234
4235 with localcontext() as c:
4236 c.prec = 1
4237 c.Emax = 1
4238 c.Emin = -1
4239
4240 # abs
4241 self.assertEqual(abs(Decimal("-10")), 10)
4242 # add
4243 self.assertEqual(Decimal("7") + 1, 8)
4244 # divide
4245 self.assertEqual(Decimal("10") / 5, 2)
4246 # divide_int
4247 self.assertEqual(Decimal("10") // 7, 1)
4248 # fma
4249 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4250 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4251 # three arg power
4252 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4253 # exp
4254 self.assertEqual(Decimal("1.01").exp(), 3)
4255 # is_normal
4256 self.assertIs(Decimal("0.01").is_normal(), False)
4257 # is_subnormal
4258 self.assertIs(Decimal("0.01").is_subnormal(), True)
4259 # ln
4260 self.assertEqual(Decimal("20").ln(), 3)
4261 # log10
4262 self.assertEqual(Decimal("20").log10(), 1)
4263 # logb
4264 self.assertEqual(Decimal("580").logb(), 2)
4265 # logical_invert
4266 self.assertEqual(Decimal("10").logical_invert(), 1)
4267 # minus
4268 self.assertEqual(-Decimal("-10"), 10)
4269 # multiply
4270 self.assertEqual(Decimal("2") * 4, 8)
4271 # next_minus
4272 self.assertEqual(Decimal("10").next_minus(), 9)
4273 # next_plus
4274 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4275 # normalize
4276 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4277 # number_class
4278 self.assertEqual(Decimal("10").number_class(), '+Normal')
4279 # plus
4280 self.assertEqual(+Decimal("-1"), -1)
4281 # remainder
4282 self.assertEqual(Decimal("10") % 7, 3)
4283 # subtract
4284 self.assertEqual(Decimal("10") - 7, 3)
4285 # to_integral_exact
4286 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4287
4288 # Boolean functions
4289 self.assertTrue(Decimal("1").is_canonical())
4290 self.assertTrue(Decimal("1").is_finite())
4291 self.assertTrue(Decimal("1").is_finite())
4292 self.assertTrue(Decimal("snan").is_snan())
4293 self.assertTrue(Decimal("-1").is_signed())
4294 self.assertTrue(Decimal("0").is_zero())
4295 self.assertTrue(Decimal("0").is_zero())
4296
4297 # Copy
4298 with localcontext() as c:
4299 c.prec = 10000
4300 x = 1228 ** 1523
4301 y = -Decimal(x)
4302
4303 z = y.copy_abs()
4304 self.assertEqual(z, x)
4305
4306 z = y.copy_negate()
4307 self.assertEqual(z, x)
4308
4309 z = y.copy_sign(Decimal(1))
4310 self.assertEqual(z, x)
4311
4312 def test_divmod(self):
4313 Decimal = self.decimal.Decimal
4314 localcontext = self.decimal.localcontext
4315 InvalidOperation = self.decimal.InvalidOperation
4316 DivisionByZero = self.decimal.DivisionByZero
4317
4318 with localcontext() as c:
4319 q, r = divmod(Decimal("10912837129"), 1001)
4320 self.assertEqual(q, Decimal('10901935'))
4321 self.assertEqual(r, Decimal('194'))
4322
4323 q, r = divmod(Decimal("NaN"), 7)
4324 self.assertTrue(q.is_nan() and r.is_nan())
4325
4326 c.traps[InvalidOperation] = False
4327 q, r = divmod(Decimal("NaN"), 7)
4328 self.assertTrue(q.is_nan() and r.is_nan())
4329
4330 c.traps[InvalidOperation] = False
4331 c.clear_flags()
4332 q, r = divmod(Decimal("inf"), Decimal("inf"))
4333 self.assertTrue(q.is_nan() and r.is_nan())
4334 self.assertTrue(c.flags[InvalidOperation])
4335
4336 c.clear_flags()
4337 q, r = divmod(Decimal("inf"), 101)
4338 self.assertTrue(q.is_infinite() and r.is_nan())
4339 self.assertTrue(c.flags[InvalidOperation])
4340
4341 c.clear_flags()
4342 q, r = divmod(Decimal(0), 0)
4343 self.assertTrue(q.is_nan() and r.is_nan())
4344 self.assertTrue(c.flags[InvalidOperation])
4345
4346 c.traps[DivisionByZero] = False
4347 c.clear_flags()
4348 q, r = divmod(Decimal(11), 0)
4349 self.assertTrue(q.is_infinite() and r.is_nan())
4350 self.assertTrue(c.flags[InvalidOperation] and
4351 c.flags[DivisionByZero])
4352
4353 def test_power(self):
4354 Decimal = self.decimal.Decimal
4355 localcontext = self.decimal.localcontext
4356 Overflow = self.decimal.Overflow
4357 Rounded = self.decimal.Rounded
4358
4359 with localcontext() as c:
4360 c.prec = 3
4361 c.clear_flags()
4362 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4363 self.assertTrue(c.flags[Rounded])
4364
4365 c.prec = 1
4366 c.Emax = 1
4367 c.Emin = -1
4368 c.clear_flags()
4369 c.traps[Overflow] = False
4370 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4371 self.assertTrue(c.flags[Overflow])
4372
4373 def test_quantize(self):
4374 Decimal = self.decimal.Decimal
4375 localcontext = self.decimal.localcontext
4376 InvalidOperation = self.decimal.InvalidOperation
4377
4378 with localcontext() as c:
4379 c.prec = 1
4380 c.Emax = 1
4381 c.Emin = -1
4382 c.traps[InvalidOperation] = False
4383 x = Decimal(99).quantize(Decimal("1e1"))
4384 self.assertTrue(x.is_nan())
4385
4386 def test_radix(self):
4387 Decimal = self.decimal.Decimal
4388 getcontext = self.decimal.getcontext
4389
4390 c = getcontext()
4391 self.assertEqual(Decimal("1").radix(), 10)
4392 self.assertEqual(c.radix(), 10)
4393
4394 def test_rop(self):
4395 Decimal = self.decimal.Decimal
4396
4397 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4398 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4399 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4400
4401 def test_round(self):
4402 # Python3 behavior: round() returns Decimal
4403 Decimal = self.decimal.Decimal
4404 getcontext = self.decimal.getcontext
4405
4406 c = getcontext()
4407 c.prec = 28
4408
4409 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4410 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4411 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4412 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4413 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4414
4415 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4416 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4417
4418 def test_create_decimal(self):
4419 c = self.decimal.Context()
4420 self.assertRaises(ValueError, c.create_decimal, ["%"])
4421
4422 def test_int(self):
4423 Decimal = self.decimal.Decimal
4424 localcontext = self.decimal.localcontext
4425
4426 with localcontext() as c:
4427 c.prec = 9999
4428 x = Decimal(1221**1271) / 10**3923
4429 self.assertEqual(int(x), 1)
4430 self.assertEqual(x.to_integral(), 2)
4431
4432 def test_copy(self):
4433 Context = self.decimal.Context
4434
4435 c = Context()
4436 c.prec = 10000
4437 x = -(1172 ** 1712)
4438
4439 y = c.copy_abs(x)
4440 self.assertEqual(y, -x)
4441
4442 y = c.copy_negate(x)
4443 self.assertEqual(y, -x)
4444
4445 y = c.copy_sign(x, 1)
4446 self.assertEqual(y, -x)
4447
4448class CCoverage(Coverage):
4449 decimal = C
4450class PyCoverage(Coverage):
4451 decimal = P
4452
4453class PyFunctionality(unittest.TestCase):
4454 """Extra functionality in decimal.py"""
4455
4456 def test_py_quantize_watchexp(self):
4457 # watchexp functionality
4458 Decimal = P.Decimal
4459 localcontext = P.localcontext
4460
4461 with localcontext() as c:
4462 c.prec = 1
4463 c.Emax = 1
4464 c.Emin = -1
4465 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4466 self.assertEqual(x, Decimal('1.00E+5'))
4467
4468 def test_py_alternate_formatting(self):
4469 # triples giving a format, a Decimal, and the expected result
4470 Decimal = P.Decimal
4471 localcontext = P.localcontext
4472
4473 test_values = [
4474 # Issue 7094: Alternate formatting (specified by #)
4475 ('.0e', '1.0', '1e+0'),
4476 ('#.0e', '1.0', '1.e+0'),
4477 ('.0f', '1.0', '1'),
4478 ('#.0f', '1.0', '1.'),
4479 ('g', '1.1', '1.1'),
4480 ('#g', '1.1', '1.1'),
4481 ('.0g', '1', '1'),
4482 ('#.0g', '1', '1.'),
4483 ('.0%', '1.0', '100%'),
4484 ('#.0%', '1.0', '100.%'),
4485 ]
4486 for fmt, d, result in test_values:
4487 self.assertEqual(format(Decimal(d), fmt), result)
4488
4489class PyWhitebox(unittest.TestCase):
4490 """White box testing for decimal.py"""
4491
4492 def test_py_exact_power(self):
4493 # Rarely exercised lines in _power_exact.
4494 Decimal = P.Decimal
4495 localcontext = P.localcontext
4496
4497 with localcontext() as c:
4498 c.prec = 8
4499 x = Decimal(2**16) ** Decimal("-0.5")
4500 self.assertEqual(x, Decimal('0.00390625'))
4501
4502 x = Decimal(2**16) ** Decimal("-0.6")
4503 self.assertEqual(x, Decimal('0.0012885819'))
4504
4505 x = Decimal("256e7") ** Decimal("-0.5")
4506
4507 x = Decimal(152587890625) ** Decimal('-0.0625')
4508 self.assertEqual(x, Decimal("0.2"))
4509
4510 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4511
4512 x = Decimal(5**2659) ** Decimal('-0.0625')
4513
4514 c.prec = 1
4515 x = Decimal("152587890625") ** Decimal('-0.5')
4516 c.prec = 201
4517 x = Decimal(2**578) ** Decimal("-0.5")
4518
4519 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004520 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004521 Decimal = P.Decimal
4522 DefaultContext = P.DefaultContext
4523 setcontext = P.setcontext
4524
4525 c = DefaultContext.copy()
4526 c.traps = dict((s, 0) for s in OrderedSignals[P])
4527 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004528
4529 d1 = Decimal('-25e55')
4530 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004531 d2 = Decimal('33e+33')
4532 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004533
4534 def checkSameDec(operation, useOther=False):
4535 if useOther:
4536 eval("d1." + operation + "(d2)")
4537 self.assertEqual(d1._sign, b1._sign)
4538 self.assertEqual(d1._int, b1._int)
4539 self.assertEqual(d1._exp, b1._exp)
4540 self.assertEqual(d2._sign, b2._sign)
4541 self.assertEqual(d2._int, b2._int)
4542 self.assertEqual(d2._exp, b2._exp)
4543 else:
4544 eval("d1." + operation + "()")
4545 self.assertEqual(d1._sign, b1._sign)
4546 self.assertEqual(d1._int, b1._int)
4547 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004548
4549 Decimal(d1)
4550 self.assertEqual(d1._sign, b1._sign)
4551 self.assertEqual(d1._int, b1._int)
4552 self.assertEqual(d1._exp, b1._exp)
4553
4554 checkSameDec("__abs__")
4555 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004556 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004557 checkSameDec("__eq__", True)
4558 checkSameDec("__ne__", True)
4559 checkSameDec("__le__", True)
4560 checkSameDec("__lt__", True)
4561 checkSameDec("__ge__", True)
4562 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004563 checkSameDec("__float__")
4564 checkSameDec("__floordiv__", True)
4565 checkSameDec("__hash__")
4566 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004567 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004568 checkSameDec("__mod__", True)
4569 checkSameDec("__mul__", True)
4570 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004571 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004572 checkSameDec("__pos__")
4573 checkSameDec("__pow__", True)
4574 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004575 checkSameDec("__rdivmod__", True)
4576 checkSameDec("__repr__")
4577 checkSameDec("__rfloordiv__", True)
4578 checkSameDec("__rmod__", True)
4579 checkSameDec("__rmul__", True)
4580 checkSameDec("__rpow__", True)
4581 checkSameDec("__rsub__", True)
4582 checkSameDec("__str__")
4583 checkSameDec("__sub__", True)
4584 checkSameDec("__truediv__", True)
4585 checkSameDec("adjusted")
4586 checkSameDec("as_tuple")
4587 checkSameDec("compare", True)
4588 checkSameDec("max", True)
4589 checkSameDec("min", True)
4590 checkSameDec("normalize")
4591 checkSameDec("quantize", True)
4592 checkSameDec("remainder_near", True)
4593 checkSameDec("same_quantum", True)
4594 checkSameDec("sqrt")
4595 checkSameDec("to_eng_string")
4596 checkSameDec("to_integral")
4597
Stefan Krah1919b7e2012-03-21 18:25:23 +01004598 def test_py_decimal_id(self):
4599 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004600
Stefan Krah1919b7e2012-03-21 18:25:23 +01004601 d = Decimal(45)
4602 e = Decimal(d)
4603 self.assertEqual(str(e), '45')
4604 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004605
Stefan Krah1919b7e2012-03-21 18:25:23 +01004606 def test_py_rescale(self):
4607 # Coverage
4608 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004609 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004610
Stefan Krah1919b7e2012-03-21 18:25:23 +01004611 with localcontext() as c:
4612 x = Decimal("NaN")._rescale(3, ROUND_UP)
4613 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004614
Stefan Krah1919b7e2012-03-21 18:25:23 +01004615 def test_py__round(self):
4616 # Coverage
4617 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004618
Stefan Krah1919b7e2012-03-21 18:25:23 +01004619 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004620
Stefan Krah1919b7e2012-03-21 18:25:23 +01004621class CFunctionality(unittest.TestCase):
4622 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004623
Stefan Krah1919b7e2012-03-21 18:25:23 +01004624 @requires_extra_functionality
4625 def test_c_ieee_context(self):
4626 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4627 IEEEContext = C.IEEEContext
4628 DECIMAL32 = C.DECIMAL32
4629 DECIMAL64 = C.DECIMAL64
4630 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004631
Stefan Krah1919b7e2012-03-21 18:25:23 +01004632 def assert_rest(self, context):
4633 self.assertEqual(context.clamp, 1)
4634 assert_signals(self, context, 'traps', [])
4635 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004636
Stefan Krah1919b7e2012-03-21 18:25:23 +01004637 c = IEEEContext(DECIMAL32)
4638 self.assertEqual(c.prec, 7)
4639 self.assertEqual(c.Emax, 96)
4640 self.assertEqual(c.Emin, -95)
4641 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004642
Stefan Krah1919b7e2012-03-21 18:25:23 +01004643 c = IEEEContext(DECIMAL64)
4644 self.assertEqual(c.prec, 16)
4645 self.assertEqual(c.Emax, 384)
4646 self.assertEqual(c.Emin, -383)
4647 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004648
Stefan Krah1919b7e2012-03-21 18:25:23 +01004649 c = IEEEContext(DECIMAL128)
4650 self.assertEqual(c.prec, 34)
4651 self.assertEqual(c.Emax, 6144)
4652 self.assertEqual(c.Emin, -6143)
4653 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004654
Stefan Krah1919b7e2012-03-21 18:25:23 +01004655 # Invalid values
4656 self.assertRaises(OverflowError, IEEEContext, 2**63)
4657 self.assertRaises(ValueError, IEEEContext, -1)
4658 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004659
Stefan Krah1919b7e2012-03-21 18:25:23 +01004660 @requires_extra_functionality
4661 def test_c_context(self):
4662 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004663
Stefan Krah1919b7e2012-03-21 18:25:23 +01004664 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4665 self.assertEqual(c._flags, C.DecClamped)
4666 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004667
Stefan Krah1919b7e2012-03-21 18:25:23 +01004668 @requires_extra_functionality
4669 def test_constants(self):
4670 # Condition flags
4671 cond = (
4672 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4673 C.DecDivisionImpossible, C.DecDivisionUndefined,
4674 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4675 C.DecInvalidOperation, C.DecMallocError,
4676 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4677 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004678 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004679
4680 # IEEEContext
4681 self.assertEqual(C.DECIMAL32, 32)
4682 self.assertEqual(C.DECIMAL64, 64)
4683 self.assertEqual(C.DECIMAL128, 128)
4684 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4685
Stefan Krah1919b7e2012-03-21 18:25:23 +01004686 # Conditions
4687 for i, v in enumerate(cond):
4688 self.assertEqual(v, 1<<i)
4689
4690 self.assertEqual(C.DecIEEEInvalidOperation,
4691 C.DecConversionSyntax|
4692 C.DecDivisionImpossible|
4693 C.DecDivisionUndefined|
4694 C.DecFpuError|
4695 C.DecInvalidContext|
4696 C.DecInvalidOperation|
4697 C.DecMallocError)
4698
4699 self.assertEqual(C.DecErrors,
4700 C.DecIEEEInvalidOperation|
4701 C.DecDivisionByZero)
4702
4703 self.assertEqual(C.DecTraps,
4704 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4705
4706class CWhitebox(unittest.TestCase):
4707 """Whitebox testing for _decimal"""
4708
4709 def test_bignum(self):
4710 # Not exactly whitebox, but too slow with pydecimal.
4711
4712 Decimal = C.Decimal
4713 localcontext = C.localcontext
4714
4715 b1 = 10**35
4716 b2 = 10**36
4717 with localcontext() as c:
4718 c.prec = 1000000
4719 for i in range(5):
4720 a = random.randrange(b1, b2)
4721 b = random.randrange(1000, 1200)
4722 x = a ** b
4723 y = Decimal(a) ** Decimal(b)
4724 self.assertEqual(x, y)
4725
4726 def test_invalid_construction(self):
4727 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4728
4729 def test_c_input_restriction(self):
4730 # Too large for _decimal to be converted exactly
4731 Decimal = C.Decimal
4732 InvalidOperation = C.InvalidOperation
4733 Context = C.Context
4734 localcontext = C.localcontext
4735
4736 with localcontext(Context()):
4737 self.assertRaises(InvalidOperation, Decimal,
4738 "1e9999999999999999999")
4739
4740 def test_c_context_repr(self):
4741 # This test is _decimal-only because flags are not printed
4742 # in the same order.
4743 DefaultContext = C.DefaultContext
4744 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004745
4746 c = DefaultContext.copy()
4747
4748 c.prec = 425000000
4749 c.Emax = 425000000
4750 c.Emin = -425000000
4751 c.rounding = ROUND_HALF_DOWN
4752 c.capitals = 0
4753 c.clamp = 1
4754 for sig in OrderedSignals[C]:
4755 c.flags[sig] = True
4756 c.traps[sig] = True
4757 c.flags[FloatOperation] = True
4758 c.traps[FloatOperation] = True
4759
4760 s = c.__repr__()
4761 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4762 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4763 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4764 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4765 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4766 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4767 self.assertEqual(s, t)
4768
4769 def test_c_context_errors(self):
4770 Context = C.Context
4771 InvalidOperation = C.InvalidOperation
4772 Overflow = C.Overflow
4773 FloatOperation = C.FloatOperation
4774 localcontext = C.localcontext
4775 getcontext = C.getcontext
4776 setcontext = C.setcontext
4777 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4778
4779 c = Context()
4780
4781 # SignalDict: input validation
4782 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4783 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4784 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4785 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4786 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4787 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4788 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4789 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4790
4791 # Test assignment from a signal dict with the correct length but
4792 # one invalid key.
4793 d = c.flags.copy()
4794 del d[FloatOperation]
4795 d["XYZ"] = 91283719
4796 self.assertRaises(KeyError, setattr, c, 'flags', d)
4797 self.assertRaises(KeyError, setattr, c, 'traps', d)
4798
4799 # Input corner cases
4800 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4801 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4802
4803 # prec, Emax, Emin
4804 for attr in ['prec', 'Emax']:
4805 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4806 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4807
4808 # prec, Emax, Emin in context constructor
4809 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4810 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4811 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4812
4813 # Overflow in conversion
4814 self.assertRaises(OverflowError, Context, prec=int_max+1)
4815 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4816 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004817 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4818 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4819
4820 # OverflowError, general ValueError
4821 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4822 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4823 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4824 if sys.platform != 'win32':
4825 self.assertRaises(ValueError, setattr, c, attr, int_max)
4826 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4827
Stefan Krah1919b7e2012-03-21 18:25:23 +01004828 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4829 if C.MAX_PREC == 425000000:
4830 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4831 int_max+1)
4832 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4833 int_max+1)
4834 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4835 -int_max-2)
4836
4837 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4838 if C.MAX_PREC == 425000000:
4839 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4840 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4841 1070000001)
4842 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4843 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4844 1070000001)
4845 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4846 -1070000001)
4847 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4848
4849 # capitals, clamp
4850 for attr in ['capitals', 'clamp']:
4851 self.assertRaises(ValueError, setattr, c, attr, -1)
4852 self.assertRaises(ValueError, setattr, c, attr, 2)
4853 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4854 if HAVE_CONFIG_64:
4855 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4856 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4857
4858 # Invalid local context
4859 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4860 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004861 self.assertRaises(TypeError, exec,
4862 'with localcontext(context=getcontext()): pass',
4863 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004864
4865 # setcontext
4866 saved_context = getcontext()
4867 self.assertRaises(TypeError, setcontext, "xyz")
4868 setcontext(saved_context)
4869
Stefan Krah59a4a932013-01-16 12:58:59 +01004870 def test_rounding_strings_interned(self):
4871
4872 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4873 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4874 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4875 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4876 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4877 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4878 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4879 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4880
Stefan Krah1919b7e2012-03-21 18:25:23 +01004881 @requires_extra_functionality
4882 def test_c_context_errors_extra(self):
4883 Context = C.Context
4884 InvalidOperation = C.InvalidOperation
4885 Overflow = C.Overflow
4886 localcontext = C.localcontext
4887 getcontext = C.getcontext
4888 setcontext = C.setcontext
4889 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4890
4891 c = Context()
4892
4893 # Input corner cases
4894 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4895
4896 # OverflowError, general ValueError
4897 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4898 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4899 if sys.platform != 'win32':
4900 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4901 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4902
4903 # OverflowError, general TypeError
4904 for attr in ('_flags', '_traps'):
4905 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4906 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4907 if sys.platform != 'win32':
4908 self.assertRaises(TypeError, setattr, c, attr, int_max)
4909 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4910
4911 # _allcr
4912 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4913 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4914 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4915 if HAVE_CONFIG_64:
4916 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4917 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4918
4919 # _flags, _traps
4920 for attr in ['_flags', '_traps']:
4921 self.assertRaises(TypeError, setattr, c, attr, 999999)
4922 self.assertRaises(TypeError, setattr, c, attr, 'x')
4923
4924 def test_c_valid_context(self):
4925 # These tests are for code coverage in _decimal.
4926 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004927 Clamped = C.Clamped
4928 Underflow = C.Underflow
4929 Inexact = C.Inexact
4930 Rounded = C.Rounded
4931 Subnormal = C.Subnormal
4932
4933 c = DefaultContext.copy()
4934
4935 # Exercise all getters and setters
4936 c.prec = 34
4937 c.rounding = ROUND_HALF_UP
4938 c.Emax = 3000
4939 c.Emin = -3000
4940 c.capitals = 1
4941 c.clamp = 0
4942
4943 self.assertEqual(c.prec, 34)
4944 self.assertEqual(c.rounding, ROUND_HALF_UP)
4945 self.assertEqual(c.Emin, -3000)
4946 self.assertEqual(c.Emax, 3000)
4947 self.assertEqual(c.capitals, 1)
4948 self.assertEqual(c.clamp, 0)
4949
4950 self.assertEqual(c.Etiny(), -3033)
4951 self.assertEqual(c.Etop(), 2967)
4952
4953 # Exercise all unsafe setters
4954 if C.MAX_PREC == 425000000:
4955 c._unsafe_setprec(999999999)
4956 c._unsafe_setemax(999999999)
4957 c._unsafe_setemin(-999999999)
4958 self.assertEqual(c.prec, 999999999)
4959 self.assertEqual(c.Emax, 999999999)
4960 self.assertEqual(c.Emin, -999999999)
4961
4962 @requires_extra_functionality
4963 def test_c_valid_context_extra(self):
4964 DefaultContext = C.DefaultContext
4965
4966 c = DefaultContext.copy()
4967 self.assertEqual(c._allcr, 1)
4968 c._allcr = 0
4969 self.assertEqual(c._allcr, 0)
4970
4971 def test_c_round(self):
4972 # Restricted input.
4973 Decimal = C.Decimal
4974 InvalidOperation = C.InvalidOperation
4975 localcontext = C.localcontext
4976 MAX_EMAX = C.MAX_EMAX
4977 MIN_ETINY = C.MIN_ETINY
4978 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4979
4980 with localcontext() as c:
4981 c.traps[InvalidOperation] = True
4982 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4983 -int_max-1)
4984 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4985 int_max)
4986 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4987 int(MAX_EMAX+1))
4988 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4989 -int(MIN_ETINY-1))
4990 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4991 -int_max-2)
4992 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4993 int_max+1)
4994
4995 def test_c_format(self):
4996 # Restricted input
4997 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004998 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4999
5000 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
5001 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
5002 self.assertRaises(TypeError, Decimal(1).__format__, [])
5003
Stefan Kraheb8c4512013-01-24 15:22:33 +01005004 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
5005 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
5006 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
5007 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005008
5009 def test_c_integral(self):
5010 Decimal = C.Decimal
5011 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01005012 localcontext = C.localcontext
5013
5014 x = Decimal(10)
5015 self.assertEqual(x.to_integral(), 10)
5016 self.assertRaises(TypeError, x.to_integral, '10')
5017 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5018 self.assertRaises(TypeError, x.to_integral, 10)
5019
5020 self.assertEqual(x.to_integral_value(), 10)
5021 self.assertRaises(TypeError, x.to_integral_value, '10')
5022 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5023 self.assertRaises(TypeError, x.to_integral_value, 10)
5024
5025 self.assertEqual(x.to_integral_exact(), 10)
5026 self.assertRaises(TypeError, x.to_integral_exact, '10')
5027 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5028 self.assertRaises(TypeError, x.to_integral_exact, 10)
5029
5030 with localcontext() as c:
5031 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5032 self.assertEqual(x, Decimal('100000000000000000000000000'))
5033
5034 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5035 self.assertEqual(x, Decimal('100000000000000000000000000'))
5036
5037 c.traps[Inexact] = True
5038 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5039
5040 def test_c_funcs(self):
5041 # Invalid arguments
5042 Decimal = C.Decimal
5043 InvalidOperation = C.InvalidOperation
5044 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005045 getcontext = C.getcontext
5046 localcontext = C.localcontext
5047
5048 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5049
5050 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5051 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5052 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5053
Raymond Hettinger771ed762009-01-03 19:20:32 +00005054 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005055 TypeError,
5056 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005057 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005058 self.assertRaises(
5059 TypeError,
5060 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5061 )
5062 self.assertRaises(
5063 TypeError,
5064 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5065 )
5066 self.assertRaises(
5067 TypeError,
5068 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5069 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005070
Stefan Krah1919b7e2012-03-21 18:25:23 +01005071 with localcontext() as c:
5072 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005073
Stefan Krah1919b7e2012-03-21 18:25:23 +01005074 # Invalid arguments
5075 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5076 self.assertRaises(TypeError, c.canonical, 200)
5077 self.assertRaises(TypeError, c.is_canonical, 200)
5078 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5079 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005080
Stefan Krah1919b7e2012-03-21 18:25:23 +01005081 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5082 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005083
Stefan Krah1919b7e2012-03-21 18:25:23 +01005084 c.traps[DivisionByZero] = True
5085 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5086 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5087 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005088
Stefan Krah1919b7e2012-03-21 18:25:23 +01005089 c.clear_flags()
5090 c.traps[InvalidOperation] = True
5091 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5092 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5093 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005094
Stefan Krah1919b7e2012-03-21 18:25:23 +01005095 c.traps[InvalidOperation] = True
5096 c.prec = 2
5097 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005098
Stefan Krah040e3112012-12-15 22:33:33 +01005099 def test_va_args_exceptions(self):
5100 Decimal = C.Decimal
5101 Context = C.Context
5102
5103 x = Decimal("10001111111")
5104
5105 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5106 'logb', 'logical_invert', 'next_minus', 'next_plus',
5107 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5108 func = getattr(x, attr)
5109 self.assertRaises(TypeError, func, context="x")
5110 self.assertRaises(TypeError, func, "x", context=None)
5111
5112 for attr in ['compare', 'compare_signal', 'logical_and',
5113 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5114 'remainder_near', 'rotate', 'scaleb', 'shift']:
5115 func = getattr(x, attr)
5116 self.assertRaises(TypeError, func, context="x")
5117 self.assertRaises(TypeError, func, "x", context=None)
5118
5119 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5120 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5121 self.assertRaises(TypeError, x.to_integral, [], [])
5122
5123 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5124 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5125 self.assertRaises(TypeError, x.to_integral_value, [], [])
5126
5127 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5128 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5129 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5130
5131 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5132 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5133
5134 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5135 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5136 self.assertRaises(TypeError, x.quantize, 1, [], [])
5137
5138 c = Context()
5139 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5140 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5141 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5142
Stefan Krah1919b7e2012-03-21 18:25:23 +01005143 @requires_extra_functionality
5144 def test_c_context_templates(self):
5145 self.assertEqual(
5146 C.BasicContext._traps,
5147 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5148 C.DecUnderflow|C.DecClamped
5149 )
5150 self.assertEqual(
5151 C.DefaultContext._traps,
5152 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5153 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005154
Stefan Krah1919b7e2012-03-21 18:25:23 +01005155 @requires_extra_functionality
5156 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005157
Stefan Krah1919b7e2012-03-21 18:25:23 +01005158 # SignalDict coverage
5159 Context = C.Context
5160 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005161
Stefan Krah1919b7e2012-03-21 18:25:23 +01005162 InvalidOperation = C.InvalidOperation
5163 DivisionByZero = C.DivisionByZero
5164 Overflow = C.Overflow
5165 Subnormal = C.Subnormal
5166 Underflow = C.Underflow
5167 Rounded = C.Rounded
5168 Inexact = C.Inexact
5169 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005170
Stefan Krah1919b7e2012-03-21 18:25:23 +01005171 DecClamped = C.DecClamped
5172 DecInvalidOperation = C.DecInvalidOperation
5173 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005174
Stefan Krah1919b7e2012-03-21 18:25:23 +01005175 def assertIsExclusivelySet(signal, signal_dict):
5176 for sig in signal_dict:
5177 if sig == signal:
5178 self.assertTrue(signal_dict[sig])
5179 else:
5180 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005181
Stefan Krah1919b7e2012-03-21 18:25:23 +01005182 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005183
Stefan Krah1919b7e2012-03-21 18:25:23 +01005184 # Signal dict methods
5185 self.assertTrue(Overflow in c.traps)
5186 c.clear_traps()
5187 for k in c.traps.keys():
5188 c.traps[k] = True
5189 for v in c.traps.values():
5190 self.assertTrue(v)
5191 c.clear_traps()
5192 for k, v in c.traps.items():
5193 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005194
Stefan Krah1919b7e2012-03-21 18:25:23 +01005195 self.assertFalse(c.flags.get(Overflow))
5196 self.assertIs(c.flags.get("x"), None)
5197 self.assertEqual(c.flags.get("x", "y"), "y")
5198 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005199
Stefan Krah1919b7e2012-03-21 18:25:23 +01005200 self.assertEqual(len(c.flags), len(c.traps))
5201 s = sys.getsizeof(c.flags)
5202 s = sys.getsizeof(c.traps)
5203 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005204
Stefan Krah1919b7e2012-03-21 18:25:23 +01005205 # Set flags/traps.
5206 c.clear_flags()
5207 c._flags = DecClamped
5208 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005209
Stefan Krah1919b7e2012-03-21 18:25:23 +01005210 c.clear_traps()
5211 c._traps = DecInvalidOperation
5212 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005213
Stefan Krah1919b7e2012-03-21 18:25:23 +01005214 # Set flags/traps from dictionary.
5215 c.clear_flags()
5216 d = c.flags.copy()
5217 d[DivisionByZero] = True
5218 c.flags = d
5219 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005220
Stefan Krah1919b7e2012-03-21 18:25:23 +01005221 c.clear_traps()
5222 d = c.traps.copy()
5223 d[Underflow] = True
5224 c.traps = d
5225 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005226
Stefan Krah1919b7e2012-03-21 18:25:23 +01005227 # Random constructors
5228 IntSignals = {
5229 Clamped: C.DecClamped,
5230 Rounded: C.DecRounded,
5231 Inexact: C.DecInexact,
5232 Subnormal: C.DecSubnormal,
5233 Underflow: C.DecUnderflow,
5234 Overflow: C.DecOverflow,
5235 DivisionByZero: C.DecDivisionByZero,
5236 InvalidOperation: C.DecIEEEInvalidOperation
5237 }
5238 IntCond = [
5239 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5240 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5241 C.DecConversionSyntax,
5242 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005243
Stefan Krah1919b7e2012-03-21 18:25:23 +01005244 lim = len(OrderedSignals[C])
5245 for r in range(lim):
5246 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005247 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005248 flags = random.sample(OrderedSignals[C], r)
5249 traps = random.sample(OrderedSignals[C], t)
5250 prec = random.randrange(1, 10000)
5251 emin = random.randrange(-10000, 0)
5252 emax = random.randrange(0, 10000)
5253 clamp = random.randrange(0, 2)
5254 caps = random.randrange(0, 2)
5255 cr = random.randrange(0, 2)
5256 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5257 capitals=caps, clamp=clamp, flags=list(flags),
5258 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005259
Stefan Krah1919b7e2012-03-21 18:25:23 +01005260 self.assertEqual(c.prec, prec)
5261 self.assertEqual(c.rounding, round)
5262 self.assertEqual(c.Emin, emin)
5263 self.assertEqual(c.Emax, emax)
5264 self.assertEqual(c.capitals, caps)
5265 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005266
Stefan Krah1919b7e2012-03-21 18:25:23 +01005267 f = 0
5268 for x in flags:
5269 f |= IntSignals[x]
5270 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005271
Stefan Krah1919b7e2012-03-21 18:25:23 +01005272 f = 0
5273 for x in traps:
5274 f |= IntSignals[x]
5275 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005276
Stefan Krah1919b7e2012-03-21 18:25:23 +01005277 for cond in IntCond:
5278 c._flags = cond
5279 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5280 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005281
Stefan Krah1919b7e2012-03-21 18:25:23 +01005282 for cond in IntCond:
5283 c._traps = cond
5284 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5285 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005286
Stefan Krah1919b7e2012-03-21 18:25:23 +01005287 def test_invalid_override(self):
5288 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005289
Stefan Krah1919b7e2012-03-21 18:25:23 +01005290 try:
5291 from locale import CHAR_MAX
5292 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06005293 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson84230a12010-02-18 14:49:50 +00005294
Stefan Krah1919b7e2012-03-21 18:25:23 +01005295 def make_grouping(lst):
5296 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005297
Stefan Krah1919b7e2012-03-21 18:25:23 +01005298 def get_fmt(x, override=None, fmt='n'):
5299 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005300
Stefan Krah1919b7e2012-03-21 18:25:23 +01005301 invalid_grouping = {
5302 'decimal_point' : ',',
5303 'grouping' : make_grouping([255, 255, 0]),
5304 'thousands_sep' : ','
5305 }
5306 invalid_dot = {
5307 'decimal_point' : 'xxxxx',
5308 'grouping' : make_grouping([3, 3, 0]),
5309 'thousands_sep' : ','
5310 }
5311 invalid_sep = {
5312 'decimal_point' : '.',
5313 'grouping' : make_grouping([3, 3, 0]),
5314 'thousands_sep' : 'yyyyy'
5315 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005316
Stefan Krah1919b7e2012-03-21 18:25:23 +01005317 if CHAR_MAX == 127: # negative grouping in override
5318 self.assertRaises(ValueError, get_fmt, 12345,
5319 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005320
Stefan Krah1919b7e2012-03-21 18:25:23 +01005321 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5322 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005323
Stefan Krah0774e9b2012-04-05 15:21:58 +02005324 def test_exact_conversion(self):
5325 Decimal = C.Decimal
5326 localcontext = C.localcontext
5327 InvalidOperation = C.InvalidOperation
5328
5329 with localcontext() as c:
5330
5331 c.traps[InvalidOperation] = True
5332
5333 # Clamped
5334 x = "0e%d" % sys.maxsize
5335 self.assertRaises(InvalidOperation, Decimal, x)
5336
5337 x = "0e%d" % (-sys.maxsize-1)
5338 self.assertRaises(InvalidOperation, Decimal, x)
5339
5340 # Overflow
5341 x = "1e%d" % sys.maxsize
5342 self.assertRaises(InvalidOperation, Decimal, x)
5343
5344 # Underflow
5345 x = "1e%d" % (-sys.maxsize-1)
5346 self.assertRaises(InvalidOperation, Decimal, x)
5347
Stefan Krahff3eca02012-04-05 15:46:19 +02005348 def test_from_tuple(self):
5349 Decimal = C.Decimal
5350 localcontext = C.localcontext
5351 InvalidOperation = C.InvalidOperation
5352 Overflow = C.Overflow
5353 Underflow = C.Underflow
5354
5355 with localcontext() as c:
5356
5357 c.traps[InvalidOperation] = True
5358 c.traps[Overflow] = True
5359 c.traps[Underflow] = True
5360
5361 # SSIZE_MAX
5362 x = (1, (), sys.maxsize)
5363 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5364 self.assertRaises(InvalidOperation, Decimal, x)
5365
5366 x = (1, (0, 1, 2), sys.maxsize)
5367 self.assertRaises(Overflow, c.create_decimal, x)
5368 self.assertRaises(InvalidOperation, Decimal, x)
5369
5370 # SSIZE_MIN
5371 x = (1, (), -sys.maxsize-1)
5372 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5373 self.assertRaises(InvalidOperation, Decimal, x)
5374
5375 x = (1, (0, 1, 2), -sys.maxsize-1)
5376 self.assertRaises(Underflow, c.create_decimal, x)
5377 self.assertRaises(InvalidOperation, Decimal, x)
5378
5379 # OverflowError
5380 x = (1, (), sys.maxsize+1)
5381 self.assertRaises(OverflowError, c.create_decimal, x)
5382 self.assertRaises(OverflowError, Decimal, x)
5383
5384 x = (1, (), -sys.maxsize-2)
5385 self.assertRaises(OverflowError, c.create_decimal, x)
5386 self.assertRaises(OverflowError, Decimal, x)
5387
5388 # Specials
5389 x = (1, (), "N")
5390 self.assertEqual(str(Decimal(x)), '-sNaN')
5391 x = (1, (0,), "N")
5392 self.assertEqual(str(Decimal(x)), '-sNaN')
5393 x = (1, (0, 1), "N")
5394 self.assertEqual(str(Decimal(x)), '-sNaN1')
5395
Stefan Krah891ca9e2013-05-29 19:14:17 +02005396 def test_sizeof(self):
5397 Decimal = C.Decimal
5398 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5399
5400 self.assertGreater(Decimal(0).__sizeof__(), 0)
5401 if HAVE_CONFIG_64:
5402 x = Decimal(10**(19*24)).__sizeof__()
5403 y = Decimal(10**(19*25)).__sizeof__()
5404 self.assertEqual(y, x+8)
5405 else:
5406 x = Decimal(10**(9*24)).__sizeof__()
5407 y = Decimal(10**(9*25)).__sizeof__()
5408 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005409
Stefan Krah1919b7e2012-03-21 18:25:23 +01005410all_tests = [
5411 CExplicitConstructionTest, PyExplicitConstructionTest,
5412 CImplicitConstructionTest, PyImplicitConstructionTest,
5413 CFormatTest, PyFormatTest,
5414 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5415 CThreadingTest, PyThreadingTest,
5416 CUsabilityTest, PyUsabilityTest,
5417 CPythonAPItests, PyPythonAPItests,
5418 CContextAPItests, PyContextAPItests,
5419 CContextWithStatement, PyContextWithStatement,
5420 CContextFlags, PyContextFlags,
5421 CSpecialContexts, PySpecialContexts,
5422 CContextInputValidation, PyContextInputValidation,
5423 CContextSubclassing, PyContextSubclassing,
5424 CCoverage, PyCoverage,
5425 CFunctionality, PyFunctionality,
5426 CWhitebox, PyWhitebox,
5427 CIBMTestCases, PyIBMTestCases,
5428]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005429
Stefan Krah1919b7e2012-03-21 18:25:23 +01005430# Delete C tests if _decimal.so is not present.
5431if not C:
5432 all_tests = all_tests[1::2]
5433else:
5434 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005435
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005436
Zachary Ware66f29282014-06-02 16:01:29 -05005437def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005438 """ Execute the tests.
5439
Raymond Hettingered20ad82004-09-04 20:09:13 +00005440 Runs all arithmetic tests if arith is True or if the "decimal" resource
5441 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005442 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005443
Stefan Krah1919b7e2012-03-21 18:25:23 +01005444 init(C)
5445 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005446 global TEST_ALL, DEBUG
Zachary Ware66f29282014-06-02 16:01:29 -05005447 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005448 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005449
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005450 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005451 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005452 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005453 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005454
5455 # Dynamically build custom test definition for each file in the test
5456 # directory and add the definitions to the DecimalTest class. This
5457 # procedure insures that new files do not get skipped.
5458 for filename in os.listdir(directory):
5459 if '.decTest' not in filename or filename.startswith("."):
5460 continue
5461 head, tail = filename.split('.')
5462 if todo_tests is not None and head not in todo_tests:
5463 continue
5464 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005465 setattr(CIBMTestCases, 'test_' + head, tester)
5466 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005467 del filename, head, tail, tester
5468
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005469
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005470 try:
5471 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005472 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005473 from doctest import IGNORE_EXCEPTION_DETAIL
5474 savedecimal = sys.modules['decimal']
5475 if C:
5476 sys.modules['decimal'] = C
5477 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5478 sys.modules['decimal'] = P
5479 run_doctest(P, verbose)
5480 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005481 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005482 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5483 P.setcontext(ORIGINAL_CONTEXT[P])
5484 if not C:
5485 warnings.warn('C tests skipped: no module named _decimal.',
5486 UserWarning)
5487 if not orig_sys_decimal is sys.modules['decimal']:
5488 raise TestFailed("Internal error: unbalanced number of changes to "
5489 "sys.modules['decimal'].")
5490
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005491
5492if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005493 import optparse
5494 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5495 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5496 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5497 (opt, args) = p.parse_args()
5498
5499 if opt.skip:
5500 test_main(arith=False, verbose=True)
5501 elif args:
5502 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005503 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005504 test_main(arith=True, verbose=True)