blob: 8358ba6e41b2ee6179902bd0c909ce19b154deea [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'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001060 ]
1061 for fmt, d, result in test_values:
1062 self.assertEqual(format(Decimal(d), fmt), result)
1063
Stefan Krah1919b7e2012-03-21 18:25:23 +01001064 # bytes format argument
1065 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1066
Mark Dickinson79f52032009-03-17 23:12:51 +00001067 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001068 Decimal = self.decimal.Decimal
1069
Mark Dickinson79f52032009-03-17 23:12:51 +00001070 try:
1071 from locale import CHAR_MAX
1072 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06001073 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson79f52032009-03-17 23:12:51 +00001074
Stefan Krah1919b7e2012-03-21 18:25:23 +01001075 def make_grouping(lst):
1076 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1077
1078 def get_fmt(x, override=None, fmt='n'):
1079 if self.decimal == C:
1080 return Decimal(x).__format__(fmt, override)
1081 else:
1082 return Decimal(x).__format__(fmt, _localeconv=override)
1083
Mark Dickinson79f52032009-03-17 23:12:51 +00001084 # Set up some localeconv-like dictionaries
1085 en_US = {
1086 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001087 'grouping' : make_grouping([3, 3, 0]),
1088 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001089 }
1090
1091 fr_FR = {
1092 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001093 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001094 'thousands_sep' : ''
1095 }
1096
1097 ru_RU = {
1098 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001099 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001100 'thousands_sep' : ' '
1101 }
1102
1103 crazy = {
1104 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001105 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001106 'thousands_sep' : '-'
1107 }
1108
Stefan Krah1919b7e2012-03-21 18:25:23 +01001109 dotsep_wide = {
1110 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1111 'grouping': make_grouping([3, 3, 0]),
1112 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1113 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001114
1115 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1116 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1117 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1118 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1119
1120 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1121 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1122 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1123 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1124
1125 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1126 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1127 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1128 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1129
Mark Dickinson7303b592009-03-18 08:25:36 +00001130 # zero padding
1131 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1132 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1133 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1134 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1135
1136 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1137 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1138 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1139 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1140 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1141 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1142
1143 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1144 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1145 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1146 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1147 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1148 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1149 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1150 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1151
Stefan Krah1919b7e2012-03-21 18:25:23 +01001152 # wide char separator and decimal point
1153 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1154 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001155
Stefan Krah6fb204a2012-09-28 16:18:54 +02001156 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001157 def test_wide_char_separator_decimal_point(self):
1158 # locale with wide char separator and decimal point
Stefan Krah8a491a82012-09-28 17:17:11 +02001159 import locale
Stefan Krah1919b7e2012-03-21 18:25:23 +01001160 Decimal = self.decimal.Decimal
1161
Stefan Krah8a491a82012-09-28 17:17:11 +02001162 decimal_point = locale.localeconv()['decimal_point']
1163 thousands_sep = locale.localeconv()['thousands_sep']
Zachary Ware9fe6d862013-12-08 00:20:35 -06001164 if decimal_point != '\u066b':
1165 self.skipTest('inappropriate decimal point separator'
Zachary Ware0f533ac2013-12-12 10:32:16 -06001166 '({!a} not {!a})'.format(decimal_point, '\u066b'))
Zachary Ware9fe6d862013-12-08 00:20:35 -06001167 if thousands_sep != '\u066c':
1168 self.skipTest('inappropriate thousands separator'
Zachary Ware0f533ac2013-12-12 10:32:16 -06001169 '({!a} not {!a})'.format(thousands_sep, '\u066c'))
Stefan Krah8a491a82012-09-28 17:17:11 +02001170
Stefan Krah1919b7e2012-03-21 18:25:23 +01001171 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1172 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001173
1174class CFormatTest(FormatTest):
1175 decimal = C
1176class PyFormatTest(FormatTest):
1177 decimal = P
1178
1179class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001180 '''Unit tests for all arithmetic operators, binary and unary.'''
1181
1182 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001183 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001184
1185 d1 = Decimal('-11.1')
1186 d2 = Decimal('22.2')
1187
1188 #two Decimals
1189 self.assertEqual(d1+d2, Decimal('11.1'))
1190 self.assertEqual(d2+d1, Decimal('11.1'))
1191
1192 #with other type, left
1193 c = d1 + 5
1194 self.assertEqual(c, Decimal('-6.1'))
1195 self.assertEqual(type(c), type(d1))
1196
1197 #with other type, right
1198 c = 5 + d1
1199 self.assertEqual(c, Decimal('-6.1'))
1200 self.assertEqual(type(c), type(d1))
1201
1202 #inline with decimal
1203 d1 += d2
1204 self.assertEqual(d1, Decimal('11.1'))
1205
1206 #inline with other type
1207 d1 += 5
1208 self.assertEqual(d1, Decimal('16.1'))
1209
1210 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001211 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001212
1213 d1 = Decimal('-11.1')
1214 d2 = Decimal('22.2')
1215
1216 #two Decimals
1217 self.assertEqual(d1-d2, Decimal('-33.3'))
1218 self.assertEqual(d2-d1, Decimal('33.3'))
1219
1220 #with other type, left
1221 c = d1 - 5
1222 self.assertEqual(c, Decimal('-16.1'))
1223 self.assertEqual(type(c), type(d1))
1224
1225 #with other type, right
1226 c = 5 - d1
1227 self.assertEqual(c, Decimal('16.1'))
1228 self.assertEqual(type(c), type(d1))
1229
1230 #inline with decimal
1231 d1 -= d2
1232 self.assertEqual(d1, Decimal('-33.3'))
1233
1234 #inline with other type
1235 d1 -= 5
1236 self.assertEqual(d1, Decimal('-38.3'))
1237
1238 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001239 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001240
1241 d1 = Decimal('-5')
1242 d2 = Decimal('3')
1243
1244 #two Decimals
1245 self.assertEqual(d1*d2, Decimal('-15'))
1246 self.assertEqual(d2*d1, Decimal('-15'))
1247
1248 #with other type, left
1249 c = d1 * 5
1250 self.assertEqual(c, Decimal('-25'))
1251 self.assertEqual(type(c), type(d1))
1252
1253 #with other type, right
1254 c = 5 * d1
1255 self.assertEqual(c, Decimal('-25'))
1256 self.assertEqual(type(c), type(d1))
1257
1258 #inline with decimal
1259 d1 *= d2
1260 self.assertEqual(d1, Decimal('-15'))
1261
1262 #inline with other type
1263 d1 *= 5
1264 self.assertEqual(d1, Decimal('-75'))
1265
1266 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001267 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001268
1269 d1 = Decimal('-5')
1270 d2 = Decimal('2')
1271
1272 #two Decimals
1273 self.assertEqual(d1/d2, Decimal('-2.5'))
1274 self.assertEqual(d2/d1, Decimal('-0.4'))
1275
1276 #with other type, left
1277 c = d1 / 4
1278 self.assertEqual(c, Decimal('-1.25'))
1279 self.assertEqual(type(c), type(d1))
1280
1281 #with other type, right
1282 c = 4 / d1
1283 self.assertEqual(c, Decimal('-0.8'))
1284 self.assertEqual(type(c), type(d1))
1285
1286 #inline with decimal
1287 d1 /= d2
1288 self.assertEqual(d1, Decimal('-2.5'))
1289
1290 #inline with other type
1291 d1 /= 4
1292 self.assertEqual(d1, Decimal('-0.625'))
1293
1294 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001295 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001296
1297 d1 = Decimal('5')
1298 d2 = Decimal('2')
1299
1300 #two Decimals
1301 self.assertEqual(d1//d2, Decimal('2'))
1302 self.assertEqual(d2//d1, Decimal('0'))
1303
1304 #with other type, left
1305 c = d1 // 4
1306 self.assertEqual(c, Decimal('1'))
1307 self.assertEqual(type(c), type(d1))
1308
1309 #with other type, right
1310 c = 7 // d1
1311 self.assertEqual(c, Decimal('1'))
1312 self.assertEqual(type(c), type(d1))
1313
1314 #inline with decimal
1315 d1 //= d2
1316 self.assertEqual(d1, Decimal('2'))
1317
1318 #inline with other type
1319 d1 //= 2
1320 self.assertEqual(d1, Decimal('1'))
1321
1322 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001323 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001324
1325 d1 = Decimal('5')
1326 d2 = Decimal('2')
1327
1328 #two Decimals
1329 self.assertEqual(d1**d2, Decimal('25'))
1330 self.assertEqual(d2**d1, Decimal('32'))
1331
1332 #with other type, left
1333 c = d1 ** 4
1334 self.assertEqual(c, Decimal('625'))
1335 self.assertEqual(type(c), type(d1))
1336
1337 #with other type, right
1338 c = 7 ** d1
1339 self.assertEqual(c, Decimal('16807'))
1340 self.assertEqual(type(c), type(d1))
1341
1342 #inline with decimal
1343 d1 **= d2
1344 self.assertEqual(d1, Decimal('25'))
1345
1346 #inline with other type
1347 d1 **= 4
1348 self.assertEqual(d1, Decimal('390625'))
1349
1350 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001351 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001352
1353 d1 = Decimal('5')
1354 d2 = Decimal('2')
1355
1356 #two Decimals
1357 self.assertEqual(d1%d2, Decimal('1'))
1358 self.assertEqual(d2%d1, Decimal('2'))
1359
1360 #with other type, left
1361 c = d1 % 4
1362 self.assertEqual(c, Decimal('1'))
1363 self.assertEqual(type(c), type(d1))
1364
1365 #with other type, right
1366 c = 7 % d1
1367 self.assertEqual(c, Decimal('2'))
1368 self.assertEqual(type(c), type(d1))
1369
1370 #inline with decimal
1371 d1 %= d2
1372 self.assertEqual(d1, Decimal('1'))
1373
1374 #inline with other type
1375 d1 %= 4
1376 self.assertEqual(d1, Decimal('1'))
1377
1378 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001379 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001380
1381 d1 = Decimal('5')
1382 d2 = Decimal('2')
1383
1384 #two Decimals
1385 (p, q) = divmod(d1, d2)
1386 self.assertEqual(p, Decimal('2'))
1387 self.assertEqual(q, Decimal('1'))
1388 self.assertEqual(type(p), type(d1))
1389 self.assertEqual(type(q), type(d1))
1390
1391 #with other type, left
1392 (p, q) = divmod(d1, 4)
1393 self.assertEqual(p, Decimal('1'))
1394 self.assertEqual(q, Decimal('1'))
1395 self.assertEqual(type(p), type(d1))
1396 self.assertEqual(type(q), type(d1))
1397
1398 #with other type, right
1399 (p, q) = divmod(7, d1)
1400 self.assertEqual(p, Decimal('1'))
1401 self.assertEqual(q, Decimal('2'))
1402 self.assertEqual(type(p), type(d1))
1403 self.assertEqual(type(q), type(d1))
1404
1405 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001406 Decimal = self.decimal.Decimal
1407
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001408 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1409 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1410 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1411
Christian Heimes77c02eb2008-02-09 02:18:51 +00001412 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001413 # comparisons involving signaling nans signal InvalidOperation
1414
1415 # order comparisons (<, <=, >, >=) involving only quiet nans
1416 # also signal InvalidOperation
1417
1418 # equality comparisons (==, !=) involving only quiet nans
1419 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001420 Decimal = self.decimal.Decimal
1421 InvalidOperation = self.decimal.InvalidOperation
1422 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001423
Christian Heimes77c02eb2008-02-09 02:18:51 +00001424 n = Decimal('NaN')
1425 s = Decimal('sNaN')
1426 i = Decimal('Inf')
1427 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001428
1429 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1430 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1431 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1432 equality_ops = operator.eq, operator.ne
1433
1434 # results when InvalidOperation is not trapped
1435 for x, y in qnan_pairs + snan_pairs:
1436 for op in order_ops + equality_ops:
1437 got = op(x, y)
1438 expected = True if op is operator.ne else False
1439 self.assertIs(expected, got,
1440 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1441 "got {4!r}".format(
1442 expected, op.__name__, x, y, got))
1443
1444 # repeat the above, but this time trap the InvalidOperation
1445 with localcontext() as ctx:
1446 ctx.traps[InvalidOperation] = 1
1447
1448 for x, y in qnan_pairs:
1449 for op in equality_ops:
1450 got = op(x, y)
1451 expected = True if op is operator.ne else False
1452 self.assertIs(expected, got,
1453 "expected {0!r} for "
1454 "operator.{1}({2!r}, {3!r}); "
1455 "got {4!r}".format(
1456 expected, op.__name__, x, y, got))
1457
1458 for x, y in snan_pairs:
1459 for op in equality_ops:
1460 self.assertRaises(InvalidOperation, operator.eq, x, y)
1461 self.assertRaises(InvalidOperation, operator.ne, x, y)
1462
1463 for x, y in qnan_pairs + snan_pairs:
1464 for op in order_ops:
1465 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001466
Mark Dickinson84230a12010-02-18 14:49:50 +00001467 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001468 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001469
Stefan Krah1919b7e2012-03-21 18:25:23 +01001470 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001471 self.assertEqual(Decimal(1).copy_sign(-2), d)
1472 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1473
Stefan Krah1919b7e2012-03-21 18:25:23 +01001474class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1475 decimal = C
1476class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1477 decimal = P
1478
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001479# The following are two functions used to test threading in the next class
1480
1481def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001482 Decimal = cls.decimal.Decimal
1483 InvalidOperation = cls.decimal.InvalidOperation
1484 DivisionByZero = cls.decimal.DivisionByZero
1485 Overflow = cls.decimal.Overflow
1486 Underflow = cls.decimal.Underflow
1487 Inexact = cls.decimal.Inexact
1488 getcontext = cls.decimal.getcontext
1489 localcontext = cls.decimal.localcontext
1490
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001491 d1 = Decimal(1)
1492 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001493 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001494
Stefan Krah1919b7e2012-03-21 18:25:23 +01001495 cls.finish1.set()
1496 cls.synchro.wait()
1497
1498 test2 = d1/d3
1499 with localcontext() as c2:
1500 cls.assertTrue(c2.flags[Inexact])
1501 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1502 cls.assertTrue(c2.flags[DivisionByZero])
1503 with localcontext() as c3:
1504 cls.assertTrue(c3.flags[Inexact])
1505 cls.assertTrue(c3.flags[DivisionByZero])
1506 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1507 cls.assertTrue(c3.flags[InvalidOperation])
1508 del c3
1509 cls.assertFalse(c2.flags[InvalidOperation])
1510 del c2
1511
1512 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1513 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1514
1515 c1 = getcontext()
1516 cls.assertTrue(c1.flags[Inexact])
1517 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1518 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001519
1520def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001521 Decimal = cls.decimal.Decimal
1522 InvalidOperation = cls.decimal.InvalidOperation
1523 DivisionByZero = cls.decimal.DivisionByZero
1524 Overflow = cls.decimal.Overflow
1525 Underflow = cls.decimal.Underflow
1526 Inexact = cls.decimal.Inexact
1527 getcontext = cls.decimal.getcontext
1528 localcontext = cls.decimal.localcontext
1529
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001530 d1 = Decimal(1)
1531 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001532 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001533
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001534 thiscontext = getcontext()
1535 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001536 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001537
1538 with localcontext() as c2:
1539 cls.assertTrue(c2.flags[Inexact])
1540 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1541 cls.assertTrue(c2.flags[Overflow])
1542 with localcontext(thiscontext) as c3:
1543 cls.assertTrue(c3.flags[Inexact])
1544 cls.assertFalse(c3.flags[Overflow])
1545 c3.traps[Underflow] = True
1546 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1547 cls.assertTrue(c3.flags[Underflow])
1548 del c3
1549 cls.assertFalse(c2.flags[Underflow])
1550 cls.assertFalse(c2.traps[Underflow])
1551 del c2
1552
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001553 cls.synchro.set()
1554 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001555
Stefan Krah1919b7e2012-03-21 18:25:23 +01001556 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001557 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001558
1559 cls.assertFalse(thiscontext.traps[Underflow])
1560 cls.assertTrue(thiscontext.flags[Inexact])
1561 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1562 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001563
Stefan Krah1919b7e2012-03-21 18:25:23 +01001564class ThreadingTest(unittest.TestCase):
1565 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001566
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001567 # Take care executing this test from IDLE, there's an issue in threading
1568 # that hangs IDLE and I couldn't find it
1569
1570 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001571 DefaultContext = self.decimal.DefaultContext
1572
1573 if self.decimal == C and not self.decimal.HAVE_THREADS:
1574 self.skipTest("compiled without threading")
1575 # Test the "threading isolation" of a Context. Also test changing
1576 # the DefaultContext, which acts as a template for the thread-local
1577 # contexts.
1578 save_prec = DefaultContext.prec
1579 save_emax = DefaultContext.Emax
1580 save_emin = DefaultContext.Emin
1581 DefaultContext.prec = 24
1582 DefaultContext.Emax = 425000000
1583 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001584
1585 self.synchro = threading.Event()
1586 self.finish1 = threading.Event()
1587 self.finish2 = threading.Event()
1588
1589 th1 = threading.Thread(target=thfunc1, args=(self,))
1590 th2 = threading.Thread(target=thfunc2, args=(self,))
1591
1592 th1.start()
1593 th2.start()
1594
1595 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001596 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001597
1598 for sig in Signals[self.decimal]:
1599 self.assertFalse(DefaultContext.flags[sig])
1600
1601 DefaultContext.prec = save_prec
1602 DefaultContext.Emax = save_emax
1603 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001604
Stefan Krah1919b7e2012-03-21 18:25:23 +01001605@unittest.skipUnless(threading, 'threading required')
1606class CThreadingTest(ThreadingTest):
1607 decimal = C
1608@unittest.skipUnless(threading, 'threading required')
1609class PyThreadingTest(ThreadingTest):
1610 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001611
Stefan Krah1919b7e2012-03-21 18:25:23 +01001612class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001613 '''Unit tests for Usability cases of Decimal.'''
1614
1615 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001616
Stefan Krah1919b7e2012-03-21 18:25:23 +01001617 Decimal = self.decimal.Decimal
1618
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001619 da = Decimal('23.42')
1620 db = Decimal('23.42')
1621 dc = Decimal('45')
1622
1623 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001624 self.assertGreater(dc, da)
1625 self.assertGreaterEqual(dc, da)
1626 self.assertLess(da, dc)
1627 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001628 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001629 self.assertNotEqual(da, dc)
1630 self.assertLessEqual(da, db)
1631 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001632
1633 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001634 self.assertGreater(dc, 23)
1635 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001636 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001637
1638 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001639 self.assertNotEqual(da, 'ugly')
1640 self.assertNotEqual(da, 32.7)
1641 self.assertNotEqual(da, object())
1642 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001643
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001644 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001645 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001646 b = a[:]
1647 random.shuffle(a)
1648 a.sort()
1649 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001650
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001651 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001652 Decimal = self.decimal.Decimal
1653
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001654 da = Decimal('0.25')
1655 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001656 self.assertLess(da, 3.0)
1657 self.assertLessEqual(da, 3.0)
1658 self.assertGreater(db, 0.25)
1659 self.assertGreaterEqual(db, 0.25)
1660 self.assertNotEqual(da, 1.5)
1661 self.assertEqual(da, 0.25)
1662 self.assertGreater(3.0, da)
1663 self.assertGreaterEqual(3.0, da)
1664 self.assertLess(0.25, db)
1665 self.assertLessEqual(0.25, db)
1666 self.assertNotEqual(0.25, db)
1667 self.assertEqual(3.0, db)
1668 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001669
Stefan Krah1919b7e2012-03-21 18:25:23 +01001670 def test_decimal_complex_comparison(self):
1671 Decimal = self.decimal.Decimal
1672
1673 da = Decimal('0.25')
1674 db = Decimal('3.0')
1675 self.assertNotEqual(da, (1.5+0j))
1676 self.assertNotEqual((1.5+0j), da)
1677 self.assertEqual(da, (0.25+0j))
1678 self.assertEqual((0.25+0j), da)
1679 self.assertEqual((3.0+0j), db)
1680 self.assertEqual(db, (3.0+0j))
1681
1682 self.assertNotEqual(db, (3.0+1j))
1683 self.assertNotEqual((3.0+1j), db)
1684
1685 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1686 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1687 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1688 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1689
1690 def test_decimal_fraction_comparison(self):
1691 D = self.decimal.Decimal
1692 F = fractions[self.decimal].Fraction
1693 Context = self.decimal.Context
1694 localcontext = self.decimal.localcontext
1695 InvalidOperation = self.decimal.InvalidOperation
1696
1697
1698 emax = C.MAX_EMAX if C else 999999999
1699 emin = C.MIN_EMIN if C else -999999999
1700 etiny = C.MIN_ETINY if C else -1999999997
1701 c = Context(Emax=emax, Emin=emin)
1702
1703 with localcontext(c):
1704 c.prec = emax
1705 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1706 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1707 self.assertLess(F(0,1), D("1e" + str(etiny)))
1708 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1709 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1710 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1711
1712 self.assertEqual(D("0.1"), F(1,10))
1713 self.assertEqual(F(1,10), D("0.1"))
1714
1715 c.prec = 300
1716 self.assertNotEqual(D(1)/3, F(1,3))
1717 self.assertNotEqual(F(1,3), D(1)/3)
1718
1719 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1720 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1721
1722 self.assertGreater(D('inf'), F(99999999999,123))
1723 self.assertGreater(D('inf'), F(-99999999999,123))
1724 self.assertLess(D('-inf'), F(99999999999,123))
1725 self.assertLess(D('-inf'), F(-99999999999,123))
1726
1727 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1728 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1729 self.assertNotEqual(D('nan'), F(-9,123))
1730 self.assertNotEqual(F(-9,123), D('nan'))
1731
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001732 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001733 Decimal = self.decimal.Decimal
1734
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001735 d = Decimal('43.24')
1736 c = copy.copy(d)
1737 self.assertEqual(id(c), id(d))
1738 dc = copy.deepcopy(d)
1739 self.assertEqual(id(dc), id(d))
1740
1741 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001742
1743 Decimal = self.decimal.Decimal
1744 localcontext = self.decimal.localcontext
1745
Stefan Krahdc817b22010-11-17 11:16:34 +00001746 def hashit(d):
1747 a = hash(d)
1748 b = d.__hash__()
1749 self.assertEqual(a, b)
1750 return a
1751
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001752 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001753 hashit(Decimal(23))
1754 hashit(Decimal('Infinity'))
1755 hashit(Decimal('-Infinity'))
1756 hashit(Decimal('nan123'))
1757 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001758
1759 test_values = [Decimal(sign*(2**m + n))
1760 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001761 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001762 for n in range(-10, 10)
1763 for sign in [-1, 1]]
1764 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001765 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001766 Decimal("-0"), # zeros
1767 Decimal("0.00"),
1768 Decimal("-0.000"),
1769 Decimal("0E10"),
1770 Decimal("-0E12"),
1771 Decimal("10.0"), # negative exponent
1772 Decimal("-23.00000"),
1773 Decimal("1230E100"), # positive exponent
1774 Decimal("-4.5678E50"),
1775 # a value for which hash(n) != hash(n % (2**64-1))
1776 # in Python pre-2.6
1777 Decimal(2**64 + 2**32 - 1),
1778 # selection of values which fail with the old (before
1779 # version 2.6) long.__hash__
1780 Decimal("1.634E100"),
1781 Decimal("90.697E100"),
1782 Decimal("188.83E100"),
1783 Decimal("1652.9E100"),
1784 Decimal("56531E100"),
1785 ])
1786
1787 # check that hash(d) == hash(int(d)) for integral values
1788 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001789 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001790
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001791 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001792 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001793 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001794 self.assertTrue(hashit(Decimal('Inf')))
1795 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001796
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001797 # check that the hashes of a Decimal float match when they
1798 # represent exactly the same values
1799 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1800 '34.0', '2.5', '112390.625', '-0.515625']
1801 for s in test_strings:
1802 f = float(s)
1803 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001804 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001805
Stefan Krah1919b7e2012-03-21 18:25:23 +01001806 with localcontext() as c:
1807 # check that the value of the hash doesn't depend on the
1808 # current context (issue #1757)
1809 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001810
Stefan Krah1919b7e2012-03-21 18:25:23 +01001811 c.prec = 6
1812 h1 = hashit(x)
1813 c.prec = 10
1814 h2 = hashit(x)
1815 c.prec = 16
1816 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001817
Stefan Krah1919b7e2012-03-21 18:25:23 +01001818 self.assertEqual(h1, h2)
1819 self.assertEqual(h1, h3)
1820
1821 c.prec = 10000
1822 x = 1100 ** 1248
1823 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001824
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001825 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001826 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001827
1828 d1 = Decimal('15.32')
1829 d2 = Decimal('28.5')
1830 l1 = 15
1831 l2 = 28
1832
1833 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001834 self.assertIs(min(d1,d2), d1)
1835 self.assertIs(min(d2,d1), d1)
1836 self.assertIs(max(d1,d2), d2)
1837 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001838
Serhiy Storchaka95949422013-08-27 19:40:23 +03001839 #between Decimal and int
Ezio Melotti6607d512010-04-03 14:59:49 +00001840 self.assertIs(min(d1,l2), d1)
1841 self.assertIs(min(l2,d1), d1)
1842 self.assertIs(max(l1,d2), d2)
1843 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001844
1845 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001846 Decimal = self.decimal.Decimal
1847
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001848 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001849 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001850 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001851 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001852
1853 def test_tostring_methods(self):
1854 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001855 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001856
1857 d = Decimal('15.32')
1858 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001859 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001860
1861 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001862 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001863 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001864
1865 d1 = Decimal('66')
1866 d2 = Decimal('15.32')
1867
1868 #int
1869 self.assertEqual(int(d1), 66)
1870 self.assertEqual(int(d2), 15)
1871
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001872 #float
1873 self.assertEqual(float(d1), 66)
1874 self.assertEqual(float(d2), 15.32)
1875
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001876 #floor
1877 test_pairs = [
1878 ('123.00', 123),
1879 ('3.2', 3),
1880 ('3.54', 3),
1881 ('3.899', 3),
1882 ('-2.3', -3),
1883 ('-11.0', -11),
1884 ('0.0', 0),
1885 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001886 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001887 ]
1888 for d, i in test_pairs:
1889 self.assertEqual(math.floor(Decimal(d)), i)
1890 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1891 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1892 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1893 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1894 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1895
1896 #ceiling
1897 test_pairs = [
1898 ('123.00', 123),
1899 ('3.2', 4),
1900 ('3.54', 4),
1901 ('3.899', 4),
1902 ('-2.3', -2),
1903 ('-11.0', -11),
1904 ('0.0', 0),
1905 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001906 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001907 ]
1908 for d, i in test_pairs:
1909 self.assertEqual(math.ceil(Decimal(d)), i)
1910 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1911 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1912 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1913 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1914 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1915
1916 #round, single argument
1917 test_pairs = [
1918 ('123.00', 123),
1919 ('3.2', 3),
1920 ('3.54', 4),
1921 ('3.899', 4),
1922 ('-2.3', -2),
1923 ('-11.0', -11),
1924 ('0.0', 0),
1925 ('-0E3', 0),
1926 ('-3.5', -4),
1927 ('-2.5', -2),
1928 ('-1.5', -2),
1929 ('-0.5', 0),
1930 ('0.5', 0),
1931 ('1.5', 2),
1932 ('2.5', 2),
1933 ('3.5', 4),
1934 ]
1935 for d, i in test_pairs:
1936 self.assertEqual(round(Decimal(d)), i)
1937 self.assertRaises(ValueError, round, Decimal('-NaN'))
1938 self.assertRaises(ValueError, round, Decimal('sNaN'))
1939 self.assertRaises(ValueError, round, Decimal('NaN123'))
1940 self.assertRaises(OverflowError, round, Decimal('Inf'))
1941 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1942
1943 #round, two arguments; this is essentially equivalent
1944 #to quantize, which is already extensively tested
1945 test_triples = [
1946 ('123.456', -4, '0E+4'),
1947 ('123.456', -3, '0E+3'),
1948 ('123.456', -2, '1E+2'),
1949 ('123.456', -1, '1.2E+2'),
1950 ('123.456', 0, '123'),
1951 ('123.456', 1, '123.5'),
1952 ('123.456', 2, '123.46'),
1953 ('123.456', 3, '123.456'),
1954 ('123.456', 4, '123.4560'),
1955 ('123.455', 2, '123.46'),
1956 ('123.445', 2, '123.44'),
1957 ('Inf', 4, 'NaN'),
1958 ('-Inf', -23, 'NaN'),
1959 ('sNaN314', 3, 'NaN314'),
1960 ]
1961 for d, n, r in test_triples:
1962 self.assertEqual(str(round(Decimal(d), n)), r)
1963
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001964 def test_nan_to_float(self):
1965 # Test conversions of decimal NANs to float.
1966 # See http://bugs.python.org/issue15544
1967 Decimal = self.decimal.Decimal
1968 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1969 f = float(Decimal(s))
1970 self.assertTrue(math.isnan(f))
1971 sign = math.copysign(1.0, f)
1972 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1973
1974 def test_snan_to_float(self):
1975 Decimal = self.decimal.Decimal
1976 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1977 d = Decimal(s)
1978 self.assertRaises(ValueError, float, d)
1979
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001980 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001981 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001982
1983 #with zero
1984 d = Decimal( (0, (0,), 0) )
1985 self.assertEqual(d, eval(repr(d)))
1986
1987 #int
1988 d = Decimal( (1, (4, 5), 0) )
1989 self.assertEqual(d, eval(repr(d)))
1990
1991 #float
1992 d = Decimal( (0, (4, 5, 3, 4), -2) )
1993 self.assertEqual(d, eval(repr(d)))
1994
1995 #weird
1996 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1997 self.assertEqual(d, eval(repr(d)))
1998
1999 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002000 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002001
2002 #with zero
2003 d = Decimal(0)
2004 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
2005
2006 #int
2007 d = Decimal(-45)
2008 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2009
2010 #complicated string
2011 d = Decimal("-4.34913534E-17")
2012 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2013
Stefan Krah76e12172012-09-10 19:34:58 +02002014 # The '0' coefficient is implementation specific to decimal.py.
2015 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002016 d = Decimal("Infinity")
2017 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2018
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002019 #leading zeros in coefficient should be stripped
2020 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2021 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2022 d = Decimal( (1, (0, 0, 0), 37) )
2023 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2024 d = Decimal( (1, (), 37) )
2025 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2026
2027 #leading zeros in NaN diagnostic info should be stripped
2028 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2029 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2030 d = Decimal( (1, (0, 0, 0), 'N') )
2031 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2032 d = Decimal( (1, (), 'n') )
2033 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2034
Stefan Krah76e12172012-09-10 19:34:58 +02002035 # For infinities, decimal.py has always silently accepted any
2036 # coefficient tuple.
2037 d = Decimal( (0, (0,), 'F') )
2038 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2039 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2040 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2041 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2042 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002043
Stefan Krah1919b7e2012-03-21 18:25:23 +01002044 def test_subclassing(self):
2045 # Different behaviours when subclassing Decimal
2046 Decimal = self.decimal.Decimal
2047
2048 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002049 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002050
2051 d1 = MyDecimal(1)
2052 d2 = MyDecimal(2)
2053 d = d1 + d2
2054 self.assertIs(type(d), Decimal)
2055
2056 d = d1.max(d2)
2057 self.assertIs(type(d), Decimal)
2058
2059 d = copy.copy(d1)
2060 self.assertIs(type(d), MyDecimal)
2061 self.assertEqual(d, d1)
2062
2063 d = copy.deepcopy(d1)
2064 self.assertIs(type(d), MyDecimal)
2065 self.assertEqual(d, d1)
2066
Stefan Krah0f82b762012-11-08 11:17:29 +01002067 # Decimal(Decimal)
2068 d = Decimal('1.0')
2069 x = Decimal(d)
2070 self.assertIs(type(x), Decimal)
2071 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002072
Stefan Krah0f82b762012-11-08 11:17:29 +01002073 # MyDecimal(Decimal)
2074 m = MyDecimal(d)
2075 self.assertIs(type(m), MyDecimal)
2076 self.assertEqual(m, d)
2077 self.assertIs(m.y, None)
2078
2079 # Decimal(MyDecimal)
2080 x = Decimal(m)
2081 self.assertIs(type(x), Decimal)
2082 self.assertEqual(x, d)
2083
2084 # MyDecimal(MyDecimal)
2085 m.y = 9
2086 x = MyDecimal(m)
2087 self.assertIs(type(x), MyDecimal)
2088 self.assertEqual(x, d)
2089 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002090
Stefan Krah1919b7e2012-03-21 18:25:23 +01002091 def test_implicit_context(self):
2092 Decimal = self.decimal.Decimal
2093 getcontext = self.decimal.getcontext
2094
2095 # Check results when context given implicitly. (Issue 2478)
2096 c = getcontext()
2097 self.assertEqual(str(Decimal(0).sqrt()),
2098 str(c.sqrt(Decimal(0))))
2099
Stefan Krah040e3112012-12-15 22:33:33 +01002100 def test_none_args(self):
2101 Decimal = self.decimal.Decimal
2102 Context = self.decimal.Context
2103 localcontext = self.decimal.localcontext
2104 InvalidOperation = self.decimal.InvalidOperation
2105 DivisionByZero = self.decimal.DivisionByZero
2106 Overflow = self.decimal.Overflow
2107 Underflow = self.decimal.Underflow
2108 Subnormal = self.decimal.Subnormal
2109 Inexact = self.decimal.Inexact
2110 Rounded = self.decimal.Rounded
2111 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002112
2113 with localcontext(Context()) as c:
2114 c.prec = 7
2115 c.Emax = 999
2116 c.Emin = -999
2117
2118 x = Decimal("111")
2119 y = Decimal("1e9999")
2120 z = Decimal("1e-9999")
2121
2122 ##### Unary functions
2123 c.clear_flags()
2124 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2125 self.assertTrue(c.flags[Inexact])
2126 self.assertTrue(c.flags[Rounded])
2127 c.clear_flags()
2128 self.assertRaises(Overflow, y.exp, context=None)
2129 self.assertTrue(c.flags[Overflow])
2130
2131 self.assertIs(z.is_normal(context=None), False)
2132 self.assertIs(z.is_subnormal(context=None), True)
2133
2134 c.clear_flags()
2135 self.assertEqual(str(x.ln(context=None)), '4.709530')
2136 self.assertTrue(c.flags[Inexact])
2137 self.assertTrue(c.flags[Rounded])
2138 c.clear_flags()
2139 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2140 self.assertTrue(c.flags[InvalidOperation])
2141
2142 c.clear_flags()
2143 self.assertEqual(str(x.log10(context=None)), '2.045323')
2144 self.assertTrue(c.flags[Inexact])
2145 self.assertTrue(c.flags[Rounded])
2146 c.clear_flags()
2147 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2148 self.assertTrue(c.flags[InvalidOperation])
2149
2150 c.clear_flags()
2151 self.assertEqual(str(x.logb(context=None)), '2')
2152 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2153 self.assertTrue(c.flags[DivisionByZero])
2154
2155 c.clear_flags()
2156 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2157 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2158 self.assertTrue(c.flags[InvalidOperation])
2159
2160 c.clear_flags()
2161 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2162 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2163 self.assertTrue(c.flags[InvalidOperation])
2164
2165 c.clear_flags()
2166 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2167 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2168 self.assertTrue(c.flags[InvalidOperation])
2169
2170 c.clear_flags()
2171 self.assertEqual(str(z.normalize(context=None)), '0')
2172 self.assertRaises(Overflow, y.normalize, context=None)
2173 self.assertTrue(c.flags[Overflow])
2174
2175 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2176
2177 c.clear_flags()
2178 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2179 self.assertTrue(c.flags[Clamped])
2180 self.assertTrue(c.flags[Inexact])
2181 self.assertTrue(c.flags[Rounded])
2182 self.assertTrue(c.flags[Subnormal])
2183 self.assertTrue(c.flags[Underflow])
2184 c.clear_flags()
2185 self.assertRaises(Overflow, y.sqrt, context=None)
2186 self.assertTrue(c.flags[Overflow])
2187
2188 c.capitals = 0
2189 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2190 c.capitals = 1
2191
2192
2193 ##### Binary functions
2194 c.clear_flags()
2195 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2196 self.assertEqual(ans, 'NaN1287828')
2197 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2198 self.assertTrue(c.flags[InvalidOperation])
2199
2200 c.clear_flags()
2201 ans = str(x.compare_signal(8224, context=None))
2202 self.assertEqual(ans, '-1')
2203 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2204 self.assertTrue(c.flags[InvalidOperation])
2205
2206 c.clear_flags()
2207 ans = str(x.logical_and(101, context=None))
2208 self.assertEqual(ans, '101')
2209 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2210 self.assertTrue(c.flags[InvalidOperation])
2211
2212 c.clear_flags()
2213 ans = str(x.logical_or(101, context=None))
2214 self.assertEqual(ans, '111')
2215 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2216 self.assertTrue(c.flags[InvalidOperation])
2217
2218 c.clear_flags()
2219 ans = str(x.logical_xor(101, context=None))
2220 self.assertEqual(ans, '10')
2221 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2222 self.assertTrue(c.flags[InvalidOperation])
2223
2224 c.clear_flags()
2225 ans = str(x.max(101, context=None))
2226 self.assertEqual(ans, '111')
2227 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2228 self.assertTrue(c.flags[InvalidOperation])
2229
2230 c.clear_flags()
2231 ans = str(x.max_mag(101, context=None))
2232 self.assertEqual(ans, '111')
2233 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2234 self.assertTrue(c.flags[InvalidOperation])
2235
2236 c.clear_flags()
2237 ans = str(x.min(101, context=None))
2238 self.assertEqual(ans, '101')
2239 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2240 self.assertTrue(c.flags[InvalidOperation])
2241
2242 c.clear_flags()
2243 ans = str(x.min_mag(101, context=None))
2244 self.assertEqual(ans, '101')
2245 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2246 self.assertTrue(c.flags[InvalidOperation])
2247
2248 c.clear_flags()
2249 ans = str(x.remainder_near(101, context=None))
2250 self.assertEqual(ans, '10')
2251 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2252 self.assertTrue(c.flags[InvalidOperation])
2253
2254 c.clear_flags()
2255 ans = str(x.rotate(2, context=None))
2256 self.assertEqual(ans, '11100')
2257 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2258 self.assertTrue(c.flags[InvalidOperation])
2259
2260 c.clear_flags()
2261 ans = str(x.scaleb(7, context=None))
2262 self.assertEqual(ans, '1.11E+9')
2263 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2264 self.assertTrue(c.flags[InvalidOperation])
2265
2266 c.clear_flags()
2267 ans = str(x.shift(2, context=None))
2268 self.assertEqual(ans, '11100')
2269 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2270 self.assertTrue(c.flags[InvalidOperation])
2271
2272
2273 ##### Ternary functions
2274 c.clear_flags()
2275 ans = str(x.fma(2, 3, context=None))
2276 self.assertEqual(ans, '225')
2277 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2278 self.assertTrue(c.flags[Overflow])
2279
2280
2281 ##### Special cases
2282 c.rounding = ROUND_HALF_EVEN
2283 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2284 self.assertEqual(ans, '2')
2285 c.rounding = ROUND_DOWN
2286 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2287 self.assertEqual(ans, '1')
2288 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2289 self.assertEqual(ans, '2')
2290 c.clear_flags()
2291 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2292 self.assertTrue(c.flags[InvalidOperation])
2293
2294 c.rounding = ROUND_HALF_EVEN
2295 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2296 self.assertEqual(ans, '2')
2297 c.rounding = ROUND_DOWN
2298 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2299 self.assertEqual(ans, '1')
2300 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2301 self.assertEqual(ans, '2')
2302 c.clear_flags()
2303 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2304 self.assertTrue(c.flags[InvalidOperation])
2305
2306 c.rounding = ROUND_HALF_EVEN
2307 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2308 self.assertEqual(ans, '2')
2309 c.rounding = ROUND_DOWN
2310 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2311 self.assertEqual(ans, '1')
2312 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2313 self.assertEqual(ans, '2')
2314 c.clear_flags()
2315 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2316 self.assertTrue(c.flags[InvalidOperation])
2317
2318 c.rounding = ROUND_UP
2319 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2320 self.assertEqual(ans, '1.501')
2321 c.rounding = ROUND_DOWN
2322 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2323 self.assertEqual(ans, '1.500')
2324 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2325 self.assertEqual(ans, '1.501')
2326 c.clear_flags()
2327 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2328 self.assertTrue(c.flags[InvalidOperation])
2329
2330 with localcontext(Context()) as context:
2331 context.prec = 7
2332 context.Emax = 999
2333 context.Emin = -999
2334 with localcontext(ctx=None) as c:
2335 self.assertEqual(c.prec, 7)
2336 self.assertEqual(c.Emax, 999)
2337 self.assertEqual(c.Emin, -999)
2338
Stefan Krah1919b7e2012-03-21 18:25:23 +01002339 def test_conversions_from_int(self):
2340 # Check that methods taking a second Decimal argument will
2341 # always accept an integer in place of a Decimal.
2342 Decimal = self.decimal.Decimal
2343
2344 self.assertEqual(Decimal(4).compare(3),
2345 Decimal(4).compare(Decimal(3)))
2346 self.assertEqual(Decimal(4).compare_signal(3),
2347 Decimal(4).compare_signal(Decimal(3)))
2348 self.assertEqual(Decimal(4).compare_total(3),
2349 Decimal(4).compare_total(Decimal(3)))
2350 self.assertEqual(Decimal(4).compare_total_mag(3),
2351 Decimal(4).compare_total_mag(Decimal(3)))
2352 self.assertEqual(Decimal(10101).logical_and(1001),
2353 Decimal(10101).logical_and(Decimal(1001)))
2354 self.assertEqual(Decimal(10101).logical_or(1001),
2355 Decimal(10101).logical_or(Decimal(1001)))
2356 self.assertEqual(Decimal(10101).logical_xor(1001),
2357 Decimal(10101).logical_xor(Decimal(1001)))
2358 self.assertEqual(Decimal(567).max(123),
2359 Decimal(567).max(Decimal(123)))
2360 self.assertEqual(Decimal(567).max_mag(123),
2361 Decimal(567).max_mag(Decimal(123)))
2362 self.assertEqual(Decimal(567).min(123),
2363 Decimal(567).min(Decimal(123)))
2364 self.assertEqual(Decimal(567).min_mag(123),
2365 Decimal(567).min_mag(Decimal(123)))
2366 self.assertEqual(Decimal(567).next_toward(123),
2367 Decimal(567).next_toward(Decimal(123)))
2368 self.assertEqual(Decimal(1234).quantize(100),
2369 Decimal(1234).quantize(Decimal(100)))
2370 self.assertEqual(Decimal(768).remainder_near(1234),
2371 Decimal(768).remainder_near(Decimal(1234)))
2372 self.assertEqual(Decimal(123).rotate(1),
2373 Decimal(123).rotate(Decimal(1)))
2374 self.assertEqual(Decimal(1234).same_quantum(1000),
2375 Decimal(1234).same_quantum(Decimal(1000)))
2376 self.assertEqual(Decimal('9.123').scaleb(-100),
2377 Decimal('9.123').scaleb(Decimal(-100)))
2378 self.assertEqual(Decimal(456).shift(-1),
2379 Decimal(456).shift(Decimal(-1)))
2380
2381 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2382 Decimal(-12).fma(Decimal(45), Decimal(67)))
2383 self.assertEqual(Decimal(-12).fma(45, 67),
2384 Decimal(-12).fma(Decimal(45), Decimal(67)))
2385 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2386 Decimal(-12).fma(Decimal(45), Decimal(67)))
2387
2388class CUsabilityTest(UsabilityTest):
2389 decimal = C
2390class PyUsabilityTest(UsabilityTest):
2391 decimal = P
2392
2393class PythonAPItests(unittest.TestCase):
2394
2395 def test_abc(self):
2396 Decimal = self.decimal.Decimal
2397
2398 self.assertTrue(issubclass(Decimal, numbers.Number))
2399 self.assertFalse(issubclass(Decimal, numbers.Real))
2400 self.assertIsInstance(Decimal(0), numbers.Number)
2401 self.assertNotIsInstance(Decimal(0), numbers.Real)
2402
2403 def test_pickle(self):
2404 Decimal = self.decimal.Decimal
2405
2406 savedecimal = sys.modules['decimal']
2407
2408 # Round trip
2409 sys.modules['decimal'] = self.decimal
2410 d = Decimal('-3.141590000')
2411 p = pickle.dumps(d)
2412 e = pickle.loads(p)
2413 self.assertEqual(d, e)
2414
2415 if C:
2416 # Test interchangeability
2417 x = C.Decimal('-3.123e81723')
2418 y = P.Decimal('-3.123e81723')
2419
2420 sys.modules['decimal'] = C
2421 sx = pickle.dumps(x)
2422 sys.modules['decimal'] = P
2423 r = pickle.loads(sx)
2424 self.assertIsInstance(r, P.Decimal)
2425 self.assertEqual(r, y)
2426
2427 sys.modules['decimal'] = P
2428 sy = pickle.dumps(y)
2429 sys.modules['decimal'] = C
2430 r = pickle.loads(sy)
2431 self.assertIsInstance(r, C.Decimal)
2432 self.assertEqual(r, x)
2433
Stefan Krah8fb74a32014-04-29 18:24:50 +02002434 x = C.Decimal('-3.123e81723').as_tuple()
2435 y = P.Decimal('-3.123e81723').as_tuple()
2436
2437 sys.modules['decimal'] = C
2438 sx = pickle.dumps(x)
2439 sys.modules['decimal'] = P
2440 r = pickle.loads(sx)
2441 self.assertIsInstance(r, P.DecimalTuple)
2442 self.assertEqual(r, y)
2443
2444 sys.modules['decimal'] = P
2445 sy = pickle.dumps(y)
2446 sys.modules['decimal'] = C
2447 r = pickle.loads(sy)
2448 self.assertIsInstance(r, C.DecimalTuple)
2449 self.assertEqual(r, x)
2450
Stefan Krah1919b7e2012-03-21 18:25:23 +01002451 sys.modules['decimal'] = savedecimal
2452
2453 def test_int(self):
2454 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002455
2456 for x in range(-250, 250):
2457 s = '%0.2f' % (x / 100.0)
2458 # should work the same as for floats
2459 self.assertEqual(int(Decimal(s)), int(float(s)))
2460 # should work the same as to_integral in the ROUND_DOWN mode
2461 d = Decimal(s)
2462 r = d.to_integral(ROUND_DOWN)
2463 self.assertEqual(Decimal(int(d)), r)
2464
2465 self.assertRaises(ValueError, int, Decimal('-nan'))
2466 self.assertRaises(ValueError, int, Decimal('snan'))
2467 self.assertRaises(OverflowError, int, Decimal('inf'))
2468 self.assertRaises(OverflowError, int, Decimal('-inf'))
2469
2470 def test_trunc(self):
2471 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002472
2473 for x in range(-250, 250):
2474 s = '%0.2f' % (x / 100.0)
2475 # should work the same as for floats
2476 self.assertEqual(int(Decimal(s)), int(float(s)))
2477 # should work the same as to_integral in the ROUND_DOWN mode
2478 d = Decimal(s)
2479 r = d.to_integral(ROUND_DOWN)
2480 self.assertEqual(Decimal(math.trunc(d)), r)
2481
2482 def test_from_float(self):
2483
2484 Decimal = self.decimal.Decimal
2485
2486 class MyDecimal(Decimal):
2487 pass
2488
2489 self.assertTrue(issubclass(MyDecimal, Decimal))
2490
2491 r = MyDecimal.from_float(0.1)
2492 self.assertEqual(type(r), MyDecimal)
2493 self.assertEqual(str(r),
2494 '0.1000000000000000055511151231257827021181583404541015625')
2495 bigint = 12345678901234567890123456789
2496 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2497 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2498 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2499 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2500 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2501 str(Decimal('NaN')))
2502 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2503 str(Decimal('Infinity')))
2504 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2505 str(Decimal('-Infinity')))
2506 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2507 for i in range(200):
2508 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2509 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2510
2511 def test_create_decimal_from_float(self):
2512 Decimal = self.decimal.Decimal
2513 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002514 Inexact = self.decimal.Inexact
2515
2516 context = Context(prec=5, rounding=ROUND_DOWN)
2517 self.assertEqual(
2518 context.create_decimal_from_float(math.pi),
2519 Decimal('3.1415')
2520 )
2521 context = Context(prec=5, rounding=ROUND_UP)
2522 self.assertEqual(
2523 context.create_decimal_from_float(math.pi),
2524 Decimal('3.1416')
2525 )
2526 context = Context(prec=5, traps=[Inexact])
2527 self.assertRaises(
2528 Inexact,
2529 context.create_decimal_from_float,
2530 math.pi
2531 )
2532 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2533 "Decimal('-0')")
2534 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2535 "Decimal('1')")
2536 self.assertEqual(repr(context.create_decimal_from_float(10)),
2537 "Decimal('10')")
2538
2539 def test_quantize(self):
2540 Decimal = self.decimal.Decimal
2541 Context = self.decimal.Context
2542 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002543
2544 c = Context(Emax=99999, Emin=-99999)
2545 self.assertEqual(
2546 Decimal('7.335').quantize(Decimal('.01')),
2547 Decimal('7.34')
2548 )
2549 self.assertEqual(
2550 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2551 Decimal('7.33')
2552 )
2553 self.assertRaises(
2554 InvalidOperation,
2555 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2556 )
2557
2558 c = Context()
2559 d = Decimal("0.871831e800")
2560 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2561 self.assertEqual(x, Decimal('8.71E+799'))
2562
2563 def test_complex(self):
2564 Decimal = self.decimal.Decimal
2565
2566 x = Decimal("9.8182731e181273")
2567 self.assertEqual(x.real, x)
2568 self.assertEqual(x.imag, 0)
2569 self.assertEqual(x.conjugate(), x)
2570
2571 x = Decimal("1")
2572 self.assertEqual(complex(x), complex(float(1)))
2573
2574 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2575 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2576 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2577 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2578
2579 def test_named_parameters(self):
2580 D = self.decimal.Decimal
2581 Context = self.decimal.Context
2582 localcontext = self.decimal.localcontext
2583 InvalidOperation = self.decimal.InvalidOperation
2584 Overflow = self.decimal.Overflow
2585
2586 xc = Context()
2587 xc.prec = 1
2588 xc.Emax = 1
2589 xc.Emin = -1
2590
2591 with localcontext() as c:
2592 c.clear_flags()
2593
2594 self.assertEqual(D(9, xc), 9)
2595 self.assertEqual(D(9, context=xc), 9)
2596 self.assertEqual(D(context=xc, value=9), 9)
2597 self.assertEqual(D(context=xc), 0)
2598 xc.clear_flags()
2599 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2600 self.assertTrue(xc.flags[InvalidOperation])
2601 self.assertFalse(c.flags[InvalidOperation])
2602
2603 xc.clear_flags()
2604 self.assertEqual(D(2).exp(context=xc), 7)
2605 self.assertRaises(Overflow, D(8).exp, context=xc)
2606 self.assertTrue(xc.flags[Overflow])
2607 self.assertFalse(c.flags[Overflow])
2608
2609 xc.clear_flags()
2610 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2611 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2612 self.assertTrue(xc.flags[InvalidOperation])
2613 self.assertFalse(c.flags[InvalidOperation])
2614
2615 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2616 self.assertEqual(D(-1).next_minus(context=xc), -2)
2617 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2618 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2619 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2620 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2621 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2622 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2623
2624 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2625 xc.clear_flags()
2626 self.assertRaises(InvalidOperation,
2627 D("0").compare_signal, D('nan'), context=xc)
2628 self.assertTrue(xc.flags[InvalidOperation])
2629 self.assertFalse(c.flags[InvalidOperation])
2630 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2631 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2632 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2633 D('-0.3'))
2634 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2635 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2636 D('0.0'))
2637 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2638 xc.clear_flags()
2639 self.assertRaises(InvalidOperation,
2640 D("0.2").quantize, D('1e10'), context=xc)
2641 self.assertTrue(xc.flags[InvalidOperation])
2642 self.assertFalse(c.flags[InvalidOperation])
2643 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2644 D('-0.5'))
2645
2646 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2647 D('7E+1'))
2648
2649 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2650 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2651 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2652 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2653 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2654 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2655 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2656 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2657
2658 self.assertFalse(D("0.01").is_normal(context=xc))
2659 self.assertTrue(D("0.01").is_subnormal(context=xc))
2660
2661 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2662 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2663 self.assertRaises(TypeError, D(1).radix, context=xc)
2664
2665 self.assertEqual(D(-111).logb(context=xc), 2)
2666 self.assertEqual(D(0).logical_invert(context=xc), 1)
2667 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2668 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2669
2670 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2671 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2672 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2673 self.assertEqual(D('23').rotate(1, context=xc), 3)
2674 self.assertEqual(D('23').rotate(1, context=xc), 3)
2675 xc.clear_flags()
2676 self.assertRaises(Overflow,
2677 D('23').scaleb, 1, context=xc)
2678 self.assertTrue(xc.flags[Overflow])
2679 self.assertFalse(c.flags[Overflow])
2680 self.assertEqual(D('23').shift(-1, context=xc), 0)
2681
2682 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2683 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2684
Stefan Krah040e3112012-12-15 22:33:33 +01002685 self.assertEqual(D(1).canonical(), 1)
2686 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2687 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2688 self.assertRaises(TypeError, D(1).canonical, context="x")
2689 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002690
Stefan Krahb6405ef2012-03-23 14:46:48 +01002691 def test_exception_hierarchy(self):
2692
2693 decimal = self.decimal
2694 DecimalException = decimal.DecimalException
2695 InvalidOperation = decimal.InvalidOperation
2696 FloatOperation = decimal.FloatOperation
2697 DivisionByZero = decimal.DivisionByZero
2698 Overflow = decimal.Overflow
2699 Underflow = decimal.Underflow
2700 Subnormal = decimal.Subnormal
2701 Inexact = decimal.Inexact
2702 Rounded = decimal.Rounded
2703 Clamped = decimal.Clamped
2704
2705 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2706
2707 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2708 self.assertTrue(issubclass(FloatOperation, DecimalException))
2709 self.assertTrue(issubclass(FloatOperation, TypeError))
2710 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2711 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2712 self.assertTrue(issubclass(Overflow, Rounded))
2713 self.assertTrue(issubclass(Overflow, Inexact))
2714 self.assertTrue(issubclass(Overflow, DecimalException))
2715 self.assertTrue(issubclass(Underflow, Inexact))
2716 self.assertTrue(issubclass(Underflow, Rounded))
2717 self.assertTrue(issubclass(Underflow, Subnormal))
2718 self.assertTrue(issubclass(Underflow, DecimalException))
2719
2720 self.assertTrue(issubclass(Subnormal, DecimalException))
2721 self.assertTrue(issubclass(Inexact, DecimalException))
2722 self.assertTrue(issubclass(Rounded, DecimalException))
2723 self.assertTrue(issubclass(Clamped, DecimalException))
2724
2725 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2726 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2727 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2728 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2729 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2730
Stefan Krah1919b7e2012-03-21 18:25:23 +01002731class CPythonAPItests(PythonAPItests):
2732 decimal = C
2733class PyPythonAPItests(PythonAPItests):
2734 decimal = P
2735
2736class ContextAPItests(unittest.TestCase):
2737
Stefan Krah9a4ff432012-12-16 21:10:35 +01002738 def test_none_args(self):
2739 Context = self.decimal.Context
2740 InvalidOperation = self.decimal.InvalidOperation
2741 DivisionByZero = self.decimal.DivisionByZero
2742 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002743
2744 c1 = Context()
2745 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2746 capitals=None, clamp=None, flags=None, traps=None)
2747 for c in [c1, c2]:
2748 self.assertEqual(c.prec, 28)
2749 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2750 self.assertEqual(c.Emax, 999999)
2751 self.assertEqual(c.Emin, -999999)
2752 self.assertEqual(c.capitals, 1)
2753 self.assertEqual(c.clamp, 0)
2754 assert_signals(self, c, 'flags', [])
2755 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2756 Overflow])
2757
Stefan Krah59a4a932013-01-16 12:58:59 +01002758 @cpython_only
2759 def test_from_legacy_strings(self):
2760 import _testcapi
2761 c = self.decimal.Context()
2762
2763 for rnd in RoundingModes:
2764 c.rounding = _testcapi.unicode_legacy_string(rnd)
2765 self.assertEqual(c.rounding, rnd)
2766
2767 s = _testcapi.unicode_legacy_string('')
2768 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2769
2770 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2771 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2772
Stefan Krah1919b7e2012-03-21 18:25:23 +01002773 def test_pickle(self):
2774
2775 Context = self.decimal.Context
2776
2777 savedecimal = sys.modules['decimal']
2778
2779 # Round trip
2780 sys.modules['decimal'] = self.decimal
2781 c = Context()
2782 e = pickle.loads(pickle.dumps(c))
2783
2784 self.assertEqual(c.prec, e.prec)
2785 self.assertEqual(c.Emin, e.Emin)
2786 self.assertEqual(c.Emax, e.Emax)
2787 self.assertEqual(c.rounding, e.rounding)
2788 self.assertEqual(c.capitals, e.capitals)
2789 self.assertEqual(c.clamp, e.clamp)
2790 self.assertEqual(c.flags, e.flags)
2791 self.assertEqual(c.traps, e.traps)
2792
2793 # Test interchangeability
2794 combinations = [(C, P), (P, C)] if C else [(P, P)]
2795 for dumper, loader in combinations:
Stefan Krah59a4a932013-01-16 12:58:59 +01002796 for ri, _ in enumerate(RoundingModes):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002797 for fi, _ in enumerate(OrderedSignals[dumper]):
2798 for ti, _ in enumerate(OrderedSignals[dumper]):
2799
2800 prec = random.randrange(1, 100)
2801 emin = random.randrange(-100, 0)
2802 emax = random.randrange(1, 100)
2803 caps = random.randrange(2)
2804 clamp = random.randrange(2)
2805
2806 # One module dumps
2807 sys.modules['decimal'] = dumper
2808 c = dumper.Context(
2809 prec=prec, Emin=emin, Emax=emax,
Stefan Krah59a4a932013-01-16 12:58:59 +01002810 rounding=RoundingModes[ri],
Stefan Krah1919b7e2012-03-21 18:25:23 +01002811 capitals=caps, clamp=clamp,
2812 flags=OrderedSignals[dumper][:fi],
2813 traps=OrderedSignals[dumper][:ti]
2814 )
2815 s = pickle.dumps(c)
2816
2817 # The other module loads
2818 sys.modules['decimal'] = loader
2819 d = pickle.loads(s)
2820 self.assertIsInstance(d, loader.Context)
2821
2822 self.assertEqual(d.prec, prec)
2823 self.assertEqual(d.Emin, emin)
2824 self.assertEqual(d.Emax, emax)
Stefan Krah59a4a932013-01-16 12:58:59 +01002825 self.assertEqual(d.rounding, RoundingModes[ri])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002826 self.assertEqual(d.capitals, caps)
2827 self.assertEqual(d.clamp, clamp)
2828 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2829 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2830
2831 sys.modules['decimal'] = savedecimal
2832
2833 def test_equality_with_other_types(self):
2834 Decimal = self.decimal.Decimal
2835
2836 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2837 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2838
2839 def test_copy(self):
2840 # All copies should be deep
2841 Decimal = self.decimal.Decimal
2842 Context = self.decimal.Context
2843
2844 c = Context()
2845 d = c.copy()
2846 self.assertNotEqual(id(c), id(d))
2847 self.assertNotEqual(id(c.flags), id(d.flags))
2848 self.assertNotEqual(id(c.traps), id(d.traps))
2849 k1 = set(c.flags.keys())
2850 k2 = set(d.flags.keys())
2851 self.assertEqual(k1, k2)
2852 self.assertEqual(c.flags, d.flags)
2853
2854 def test__clamp(self):
2855 # In Python 3.2, the private attribute `_clamp` was made
2856 # public (issue 8540), with the old `_clamp` becoming a
2857 # property wrapping `clamp`. For the duration of Python 3.2
2858 # only, the attribute should be gettable/settable via both
2859 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2860 # removed.
2861 Context = self.decimal.Context
2862 c = Context()
2863 self.assertRaises(AttributeError, getattr, c, '_clamp')
2864
2865 def test_abs(self):
2866 Decimal = self.decimal.Decimal
2867 Context = self.decimal.Context
2868
2869 c = Context()
2870 d = c.abs(Decimal(-1))
2871 self.assertEqual(c.abs(-1), d)
2872 self.assertRaises(TypeError, c.abs, '-1')
2873
2874 def test_add(self):
2875 Decimal = self.decimal.Decimal
2876 Context = self.decimal.Context
2877
2878 c = Context()
2879 d = c.add(Decimal(1), Decimal(1))
2880 self.assertEqual(c.add(1, 1), d)
2881 self.assertEqual(c.add(Decimal(1), 1), d)
2882 self.assertEqual(c.add(1, Decimal(1)), d)
2883 self.assertRaises(TypeError, c.add, '1', 1)
2884 self.assertRaises(TypeError, c.add, 1, '1')
2885
2886 def test_compare(self):
2887 Decimal = self.decimal.Decimal
2888 Context = self.decimal.Context
2889
2890 c = Context()
2891 d = c.compare(Decimal(1), Decimal(1))
2892 self.assertEqual(c.compare(1, 1), d)
2893 self.assertEqual(c.compare(Decimal(1), 1), d)
2894 self.assertEqual(c.compare(1, Decimal(1)), d)
2895 self.assertRaises(TypeError, c.compare, '1', 1)
2896 self.assertRaises(TypeError, c.compare, 1, '1')
2897
2898 def test_compare_signal(self):
2899 Decimal = self.decimal.Decimal
2900 Context = self.decimal.Context
2901
2902 c = Context()
2903 d = c.compare_signal(Decimal(1), Decimal(1))
2904 self.assertEqual(c.compare_signal(1, 1), d)
2905 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2906 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2907 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2908 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2909
2910 def test_compare_total(self):
2911 Decimal = self.decimal.Decimal
2912 Context = self.decimal.Context
2913
2914 c = Context()
2915 d = c.compare_total(Decimal(1), Decimal(1))
2916 self.assertEqual(c.compare_total(1, 1), d)
2917 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2918 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2919 self.assertRaises(TypeError, c.compare_total, '1', 1)
2920 self.assertRaises(TypeError, c.compare_total, 1, '1')
2921
2922 def test_compare_total_mag(self):
2923 Decimal = self.decimal.Decimal
2924 Context = self.decimal.Context
2925
2926 c = Context()
2927 d = c.compare_total_mag(Decimal(1), Decimal(1))
2928 self.assertEqual(c.compare_total_mag(1, 1), d)
2929 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2930 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2931 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2932 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2933
2934 def test_copy_abs(self):
2935 Decimal = self.decimal.Decimal
2936 Context = self.decimal.Context
2937
2938 c = Context()
2939 d = c.copy_abs(Decimal(-1))
2940 self.assertEqual(c.copy_abs(-1), d)
2941 self.assertRaises(TypeError, c.copy_abs, '-1')
2942
2943 def test_copy_decimal(self):
2944 Decimal = self.decimal.Decimal
2945 Context = self.decimal.Context
2946
2947 c = Context()
2948 d = c.copy_decimal(Decimal(-1))
2949 self.assertEqual(c.copy_decimal(-1), d)
2950 self.assertRaises(TypeError, c.copy_decimal, '-1')
2951
2952 def test_copy_negate(self):
2953 Decimal = self.decimal.Decimal
2954 Context = self.decimal.Context
2955
2956 c = Context()
2957 d = c.copy_negate(Decimal(-1))
2958 self.assertEqual(c.copy_negate(-1), d)
2959 self.assertRaises(TypeError, c.copy_negate, '-1')
2960
2961 def test_copy_sign(self):
2962 Decimal = self.decimal.Decimal
2963 Context = self.decimal.Context
2964
2965 c = Context()
2966 d = c.copy_sign(Decimal(1), Decimal(-2))
2967 self.assertEqual(c.copy_sign(1, -2), d)
2968 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2969 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2970 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2971 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2972
2973 def test_divide(self):
2974 Decimal = self.decimal.Decimal
2975 Context = self.decimal.Context
2976
2977 c = Context()
2978 d = c.divide(Decimal(1), Decimal(2))
2979 self.assertEqual(c.divide(1, 2), d)
2980 self.assertEqual(c.divide(Decimal(1), 2), d)
2981 self.assertEqual(c.divide(1, Decimal(2)), d)
2982 self.assertRaises(TypeError, c.divide, '1', 2)
2983 self.assertRaises(TypeError, c.divide, 1, '2')
2984
2985 def test_divide_int(self):
2986 Decimal = self.decimal.Decimal
2987 Context = self.decimal.Context
2988
2989 c = Context()
2990 d = c.divide_int(Decimal(1), Decimal(2))
2991 self.assertEqual(c.divide_int(1, 2), d)
2992 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2993 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2994 self.assertRaises(TypeError, c.divide_int, '1', 2)
2995 self.assertRaises(TypeError, c.divide_int, 1, '2')
2996
2997 def test_divmod(self):
2998 Decimal = self.decimal.Decimal
2999 Context = self.decimal.Context
3000
3001 c = Context()
3002 d = c.divmod(Decimal(1), Decimal(2))
3003 self.assertEqual(c.divmod(1, 2), d)
3004 self.assertEqual(c.divmod(Decimal(1), 2), d)
3005 self.assertEqual(c.divmod(1, Decimal(2)), d)
3006 self.assertRaises(TypeError, c.divmod, '1', 2)
3007 self.assertRaises(TypeError, c.divmod, 1, '2')
3008
3009 def test_exp(self):
3010 Decimal = self.decimal.Decimal
3011 Context = self.decimal.Context
3012
3013 c = Context()
3014 d = c.exp(Decimal(10))
3015 self.assertEqual(c.exp(10), d)
3016 self.assertRaises(TypeError, c.exp, '10')
3017
3018 def test_fma(self):
3019 Decimal = self.decimal.Decimal
3020 Context = self.decimal.Context
3021
3022 c = Context()
3023 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3024 self.assertEqual(c.fma(2, 3, 4), d)
3025 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3026 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3027 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3028 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3029 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3030 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3031 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3032
3033 # Issue 12079 for Context.fma ...
3034 self.assertRaises(TypeError, c.fma,
3035 Decimal('Infinity'), Decimal(0), "not a decimal")
3036 self.assertRaises(TypeError, c.fma,
3037 Decimal(1), Decimal('snan'), 1.222)
3038 # ... and for Decimal.fma.
3039 self.assertRaises(TypeError, Decimal('Infinity').fma,
3040 Decimal(0), "not a decimal")
3041 self.assertRaises(TypeError, Decimal(1).fma,
3042 Decimal('snan'), 1.222)
3043
3044 def test_is_finite(self):
3045 Decimal = self.decimal.Decimal
3046 Context = self.decimal.Context
3047
3048 c = Context()
3049 d = c.is_finite(Decimal(10))
3050 self.assertEqual(c.is_finite(10), d)
3051 self.assertRaises(TypeError, c.is_finite, '10')
3052
3053 def test_is_infinite(self):
3054 Decimal = self.decimal.Decimal
3055 Context = self.decimal.Context
3056
3057 c = Context()
3058 d = c.is_infinite(Decimal(10))
3059 self.assertEqual(c.is_infinite(10), d)
3060 self.assertRaises(TypeError, c.is_infinite, '10')
3061
3062 def test_is_nan(self):
3063 Decimal = self.decimal.Decimal
3064 Context = self.decimal.Context
3065
3066 c = Context()
3067 d = c.is_nan(Decimal(10))
3068 self.assertEqual(c.is_nan(10), d)
3069 self.assertRaises(TypeError, c.is_nan, '10')
3070
3071 def test_is_normal(self):
3072 Decimal = self.decimal.Decimal
3073 Context = self.decimal.Context
3074
3075 c = Context()
3076 d = c.is_normal(Decimal(10))
3077 self.assertEqual(c.is_normal(10), d)
3078 self.assertRaises(TypeError, c.is_normal, '10')
3079
3080 def test_is_qnan(self):
3081 Decimal = self.decimal.Decimal
3082 Context = self.decimal.Context
3083
3084 c = Context()
3085 d = c.is_qnan(Decimal(10))
3086 self.assertEqual(c.is_qnan(10), d)
3087 self.assertRaises(TypeError, c.is_qnan, '10')
3088
3089 def test_is_signed(self):
3090 Decimal = self.decimal.Decimal
3091 Context = self.decimal.Context
3092
3093 c = Context()
3094 d = c.is_signed(Decimal(10))
3095 self.assertEqual(c.is_signed(10), d)
3096 self.assertRaises(TypeError, c.is_signed, '10')
3097
3098 def test_is_snan(self):
3099 Decimal = self.decimal.Decimal
3100 Context = self.decimal.Context
3101
3102 c = Context()
3103 d = c.is_snan(Decimal(10))
3104 self.assertEqual(c.is_snan(10), d)
3105 self.assertRaises(TypeError, c.is_snan, '10')
3106
3107 def test_is_subnormal(self):
3108 Decimal = self.decimal.Decimal
3109 Context = self.decimal.Context
3110
3111 c = Context()
3112 d = c.is_subnormal(Decimal(10))
3113 self.assertEqual(c.is_subnormal(10), d)
3114 self.assertRaises(TypeError, c.is_subnormal, '10')
3115
3116 def test_is_zero(self):
3117 Decimal = self.decimal.Decimal
3118 Context = self.decimal.Context
3119
3120 c = Context()
3121 d = c.is_zero(Decimal(10))
3122 self.assertEqual(c.is_zero(10), d)
3123 self.assertRaises(TypeError, c.is_zero, '10')
3124
3125 def test_ln(self):
3126 Decimal = self.decimal.Decimal
3127 Context = self.decimal.Context
3128
3129 c = Context()
3130 d = c.ln(Decimal(10))
3131 self.assertEqual(c.ln(10), d)
3132 self.assertRaises(TypeError, c.ln, '10')
3133
3134 def test_log10(self):
3135 Decimal = self.decimal.Decimal
3136 Context = self.decimal.Context
3137
3138 c = Context()
3139 d = c.log10(Decimal(10))
3140 self.assertEqual(c.log10(10), d)
3141 self.assertRaises(TypeError, c.log10, '10')
3142
3143 def test_logb(self):
3144 Decimal = self.decimal.Decimal
3145 Context = self.decimal.Context
3146
3147 c = Context()
3148 d = c.logb(Decimal(10))
3149 self.assertEqual(c.logb(10), d)
3150 self.assertRaises(TypeError, c.logb, '10')
3151
3152 def test_logical_and(self):
3153 Decimal = self.decimal.Decimal
3154 Context = self.decimal.Context
3155
3156 c = Context()
3157 d = c.logical_and(Decimal(1), Decimal(1))
3158 self.assertEqual(c.logical_and(1, 1), d)
3159 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3160 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3161 self.assertRaises(TypeError, c.logical_and, '1', 1)
3162 self.assertRaises(TypeError, c.logical_and, 1, '1')
3163
3164 def test_logical_invert(self):
3165 Decimal = self.decimal.Decimal
3166 Context = self.decimal.Context
3167
3168 c = Context()
3169 d = c.logical_invert(Decimal(1000))
3170 self.assertEqual(c.logical_invert(1000), d)
3171 self.assertRaises(TypeError, c.logical_invert, '1000')
3172
3173 def test_logical_or(self):
3174 Decimal = self.decimal.Decimal
3175 Context = self.decimal.Context
3176
3177 c = Context()
3178 d = c.logical_or(Decimal(1), Decimal(1))
3179 self.assertEqual(c.logical_or(1, 1), d)
3180 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3181 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3182 self.assertRaises(TypeError, c.logical_or, '1', 1)
3183 self.assertRaises(TypeError, c.logical_or, 1, '1')
3184
3185 def test_logical_xor(self):
3186 Decimal = self.decimal.Decimal
3187 Context = self.decimal.Context
3188
3189 c = Context()
3190 d = c.logical_xor(Decimal(1), Decimal(1))
3191 self.assertEqual(c.logical_xor(1, 1), d)
3192 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3193 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3194 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3195 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3196
3197 def test_max(self):
3198 Decimal = self.decimal.Decimal
3199 Context = self.decimal.Context
3200
3201 c = Context()
3202 d = c.max(Decimal(1), Decimal(2))
3203 self.assertEqual(c.max(1, 2), d)
3204 self.assertEqual(c.max(Decimal(1), 2), d)
3205 self.assertEqual(c.max(1, Decimal(2)), d)
3206 self.assertRaises(TypeError, c.max, '1', 2)
3207 self.assertRaises(TypeError, c.max, 1, '2')
3208
3209 def test_max_mag(self):
3210 Decimal = self.decimal.Decimal
3211 Context = self.decimal.Context
3212
3213 c = Context()
3214 d = c.max_mag(Decimal(1), Decimal(2))
3215 self.assertEqual(c.max_mag(1, 2), d)
3216 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3217 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3218 self.assertRaises(TypeError, c.max_mag, '1', 2)
3219 self.assertRaises(TypeError, c.max_mag, 1, '2')
3220
3221 def test_min(self):
3222 Decimal = self.decimal.Decimal
3223 Context = self.decimal.Context
3224
3225 c = Context()
3226 d = c.min(Decimal(1), Decimal(2))
3227 self.assertEqual(c.min(1, 2), d)
3228 self.assertEqual(c.min(Decimal(1), 2), d)
3229 self.assertEqual(c.min(1, Decimal(2)), d)
3230 self.assertRaises(TypeError, c.min, '1', 2)
3231 self.assertRaises(TypeError, c.min, 1, '2')
3232
3233 def test_min_mag(self):
3234 Decimal = self.decimal.Decimal
3235 Context = self.decimal.Context
3236
3237 c = Context()
3238 d = c.min_mag(Decimal(1), Decimal(2))
3239 self.assertEqual(c.min_mag(1, 2), d)
3240 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3241 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3242 self.assertRaises(TypeError, c.min_mag, '1', 2)
3243 self.assertRaises(TypeError, c.min_mag, 1, '2')
3244
3245 def test_minus(self):
3246 Decimal = self.decimal.Decimal
3247 Context = self.decimal.Context
3248
3249 c = Context()
3250 d = c.minus(Decimal(10))
3251 self.assertEqual(c.minus(10), d)
3252 self.assertRaises(TypeError, c.minus, '10')
3253
3254 def test_multiply(self):
3255 Decimal = self.decimal.Decimal
3256 Context = self.decimal.Context
3257
3258 c = Context()
3259 d = c.multiply(Decimal(1), Decimal(2))
3260 self.assertEqual(c.multiply(1, 2), d)
3261 self.assertEqual(c.multiply(Decimal(1), 2), d)
3262 self.assertEqual(c.multiply(1, Decimal(2)), d)
3263 self.assertRaises(TypeError, c.multiply, '1', 2)
3264 self.assertRaises(TypeError, c.multiply, 1, '2')
3265
3266 def test_next_minus(self):
3267 Decimal = self.decimal.Decimal
3268 Context = self.decimal.Context
3269
3270 c = Context()
3271 d = c.next_minus(Decimal(10))
3272 self.assertEqual(c.next_minus(10), d)
3273 self.assertRaises(TypeError, c.next_minus, '10')
3274
3275 def test_next_plus(self):
3276 Decimal = self.decimal.Decimal
3277 Context = self.decimal.Context
3278
3279 c = Context()
3280 d = c.next_plus(Decimal(10))
3281 self.assertEqual(c.next_plus(10), d)
3282 self.assertRaises(TypeError, c.next_plus, '10')
3283
3284 def test_next_toward(self):
3285 Decimal = self.decimal.Decimal
3286 Context = self.decimal.Context
3287
3288 c = Context()
3289 d = c.next_toward(Decimal(1), Decimal(2))
3290 self.assertEqual(c.next_toward(1, 2), d)
3291 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3292 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3293 self.assertRaises(TypeError, c.next_toward, '1', 2)
3294 self.assertRaises(TypeError, c.next_toward, 1, '2')
3295
3296 def test_normalize(self):
3297 Decimal = self.decimal.Decimal
3298 Context = self.decimal.Context
3299
3300 c = Context()
3301 d = c.normalize(Decimal(10))
3302 self.assertEqual(c.normalize(10), d)
3303 self.assertRaises(TypeError, c.normalize, '10')
3304
3305 def test_number_class(self):
3306 Decimal = self.decimal.Decimal
3307 Context = self.decimal.Context
3308
3309 c = Context()
3310 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3311 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3312 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3313
3314 def test_plus(self):
3315 Decimal = self.decimal.Decimal
3316 Context = self.decimal.Context
3317
3318 c = Context()
3319 d = c.plus(Decimal(10))
3320 self.assertEqual(c.plus(10), d)
3321 self.assertRaises(TypeError, c.plus, '10')
3322
3323 def test_power(self):
3324 Decimal = self.decimal.Decimal
3325 Context = self.decimal.Context
3326
3327 c = Context()
3328 d = c.power(Decimal(1), Decimal(4))
3329 self.assertEqual(c.power(1, 4), d)
3330 self.assertEqual(c.power(Decimal(1), 4), d)
3331 self.assertEqual(c.power(1, Decimal(4)), d)
3332 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3333 self.assertRaises(TypeError, c.power, '1', 4)
3334 self.assertRaises(TypeError, c.power, 1, '4')
3335 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3336
3337 def test_quantize(self):
3338 Decimal = self.decimal.Decimal
3339 Context = self.decimal.Context
3340
3341 c = Context()
3342 d = c.quantize(Decimal(1), Decimal(2))
3343 self.assertEqual(c.quantize(1, 2), d)
3344 self.assertEqual(c.quantize(Decimal(1), 2), d)
3345 self.assertEqual(c.quantize(1, Decimal(2)), d)
3346 self.assertRaises(TypeError, c.quantize, '1', 2)
3347 self.assertRaises(TypeError, c.quantize, 1, '2')
3348
3349 def test_remainder(self):
3350 Decimal = self.decimal.Decimal
3351 Context = self.decimal.Context
3352
3353 c = Context()
3354 d = c.remainder(Decimal(1), Decimal(2))
3355 self.assertEqual(c.remainder(1, 2), d)
3356 self.assertEqual(c.remainder(Decimal(1), 2), d)
3357 self.assertEqual(c.remainder(1, Decimal(2)), d)
3358 self.assertRaises(TypeError, c.remainder, '1', 2)
3359 self.assertRaises(TypeError, c.remainder, 1, '2')
3360
3361 def test_remainder_near(self):
3362 Decimal = self.decimal.Decimal
3363 Context = self.decimal.Context
3364
3365 c = Context()
3366 d = c.remainder_near(Decimal(1), Decimal(2))
3367 self.assertEqual(c.remainder_near(1, 2), d)
3368 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3369 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3370 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3371 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3372
3373 def test_rotate(self):
3374 Decimal = self.decimal.Decimal
3375 Context = self.decimal.Context
3376
3377 c = Context()
3378 d = c.rotate(Decimal(1), Decimal(2))
3379 self.assertEqual(c.rotate(1, 2), d)
3380 self.assertEqual(c.rotate(Decimal(1), 2), d)
3381 self.assertEqual(c.rotate(1, Decimal(2)), d)
3382 self.assertRaises(TypeError, c.rotate, '1', 2)
3383 self.assertRaises(TypeError, c.rotate, 1, '2')
3384
3385 def test_sqrt(self):
3386 Decimal = self.decimal.Decimal
3387 Context = self.decimal.Context
3388
3389 c = Context()
3390 d = c.sqrt(Decimal(10))
3391 self.assertEqual(c.sqrt(10), d)
3392 self.assertRaises(TypeError, c.sqrt, '10')
3393
3394 def test_same_quantum(self):
3395 Decimal = self.decimal.Decimal
3396 Context = self.decimal.Context
3397
3398 c = Context()
3399 d = c.same_quantum(Decimal(1), Decimal(2))
3400 self.assertEqual(c.same_quantum(1, 2), d)
3401 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3402 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3403 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3404 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3405
3406 def test_scaleb(self):
3407 Decimal = self.decimal.Decimal
3408 Context = self.decimal.Context
3409
3410 c = Context()
3411 d = c.scaleb(Decimal(1), Decimal(2))
3412 self.assertEqual(c.scaleb(1, 2), d)
3413 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3414 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3415 self.assertRaises(TypeError, c.scaleb, '1', 2)
3416 self.assertRaises(TypeError, c.scaleb, 1, '2')
3417
3418 def test_shift(self):
3419 Decimal = self.decimal.Decimal
3420 Context = self.decimal.Context
3421
3422 c = Context()
3423 d = c.shift(Decimal(1), Decimal(2))
3424 self.assertEqual(c.shift(1, 2), d)
3425 self.assertEqual(c.shift(Decimal(1), 2), d)
3426 self.assertEqual(c.shift(1, Decimal(2)), d)
3427 self.assertRaises(TypeError, c.shift, '1', 2)
3428 self.assertRaises(TypeError, c.shift, 1, '2')
3429
3430 def test_subtract(self):
3431 Decimal = self.decimal.Decimal
3432 Context = self.decimal.Context
3433
3434 c = Context()
3435 d = c.subtract(Decimal(1), Decimal(2))
3436 self.assertEqual(c.subtract(1, 2), d)
3437 self.assertEqual(c.subtract(Decimal(1), 2), d)
3438 self.assertEqual(c.subtract(1, Decimal(2)), d)
3439 self.assertRaises(TypeError, c.subtract, '1', 2)
3440 self.assertRaises(TypeError, c.subtract, 1, '2')
3441
3442 def test_to_eng_string(self):
3443 Decimal = self.decimal.Decimal
3444 Context = self.decimal.Context
3445
3446 c = Context()
3447 d = c.to_eng_string(Decimal(10))
3448 self.assertEqual(c.to_eng_string(10), d)
3449 self.assertRaises(TypeError, c.to_eng_string, '10')
3450
3451 def test_to_sci_string(self):
3452 Decimal = self.decimal.Decimal
3453 Context = self.decimal.Context
3454
3455 c = Context()
3456 d = c.to_sci_string(Decimal(10))
3457 self.assertEqual(c.to_sci_string(10), d)
3458 self.assertRaises(TypeError, c.to_sci_string, '10')
3459
3460 def test_to_integral_exact(self):
3461 Decimal = self.decimal.Decimal
3462 Context = self.decimal.Context
3463
3464 c = Context()
3465 d = c.to_integral_exact(Decimal(10))
3466 self.assertEqual(c.to_integral_exact(10), d)
3467 self.assertRaises(TypeError, c.to_integral_exact, '10')
3468
3469 def test_to_integral_value(self):
3470 Decimal = self.decimal.Decimal
3471 Context = self.decimal.Context
3472
3473 c = Context()
3474 d = c.to_integral_value(Decimal(10))
3475 self.assertEqual(c.to_integral_value(10), d)
3476 self.assertRaises(TypeError, c.to_integral_value, '10')
3477 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3478
3479class CContextAPItests(ContextAPItests):
3480 decimal = C
3481class PyContextAPItests(ContextAPItests):
3482 decimal = P
3483
3484class ContextWithStatement(unittest.TestCase):
3485 # Can't do these as docstrings until Python 2.6
3486 # as doctest can't handle __future__ statements
3487
3488 def test_localcontext(self):
3489 # Use a copy of the current context in the block
3490 getcontext = self.decimal.getcontext
3491 localcontext = self.decimal.localcontext
3492
3493 orig_ctx = getcontext()
3494 with localcontext() as enter_ctx:
3495 set_ctx = getcontext()
3496 final_ctx = getcontext()
3497 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3498 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3499 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3500
3501 def test_localcontextarg(self):
3502 # Use a copy of the supplied context in the block
3503 Context = self.decimal.Context
3504 getcontext = self.decimal.getcontext
3505 localcontext = self.decimal.localcontext
3506
3507 localcontext = self.decimal.localcontext
3508 orig_ctx = getcontext()
3509 new_ctx = Context(prec=42)
3510 with localcontext(new_ctx) as enter_ctx:
3511 set_ctx = getcontext()
3512 final_ctx = getcontext()
3513 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3514 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3515 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3516 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3517
3518 def test_nested_with_statements(self):
3519 # Use a copy of the supplied context in the block
3520 Decimal = self.decimal.Decimal
3521 Context = self.decimal.Context
3522 getcontext = self.decimal.getcontext
3523 localcontext = self.decimal.localcontext
3524 Clamped = self.decimal.Clamped
3525 Overflow = self.decimal.Overflow
3526
3527 orig_ctx = getcontext()
3528 orig_ctx.clear_flags()
3529 new_ctx = Context(Emax=384)
3530 with localcontext() as c1:
3531 self.assertEqual(c1.flags, orig_ctx.flags)
3532 self.assertEqual(c1.traps, orig_ctx.traps)
3533 c1.traps[Clamped] = True
3534 c1.Emin = -383
3535 self.assertNotEqual(orig_ctx.Emin, -383)
3536 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3537 self.assertTrue(c1.flags[Clamped])
3538 with localcontext(new_ctx) as c2:
3539 self.assertEqual(c2.flags, new_ctx.flags)
3540 self.assertEqual(c2.traps, new_ctx.traps)
3541 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3542 self.assertFalse(c2.flags[Clamped])
3543 self.assertTrue(c2.flags[Overflow])
3544 del c2
3545 self.assertFalse(c1.flags[Overflow])
3546 del c1
3547 self.assertNotEqual(orig_ctx.Emin, -383)
3548 self.assertFalse(orig_ctx.flags[Clamped])
3549 self.assertFalse(orig_ctx.flags[Overflow])
3550 self.assertFalse(new_ctx.flags[Clamped])
3551 self.assertFalse(new_ctx.flags[Overflow])
3552
3553 def test_with_statements_gc1(self):
3554 localcontext = self.decimal.localcontext
3555
3556 with localcontext() as c1:
3557 del c1
3558 with localcontext() as c2:
3559 del c2
3560 with localcontext() as c3:
3561 del c3
3562 with localcontext() as c4:
3563 del c4
3564
3565 def test_with_statements_gc2(self):
3566 localcontext = self.decimal.localcontext
3567
3568 with localcontext() as c1:
3569 with localcontext(c1) as c2:
3570 del c1
3571 with localcontext(c2) as c3:
3572 del c2
3573 with localcontext(c3) as c4:
3574 del c3
3575 del c4
3576
3577 def test_with_statements_gc3(self):
3578 Context = self.decimal.Context
3579 localcontext = self.decimal.localcontext
3580 getcontext = self.decimal.getcontext
3581 setcontext = self.decimal.setcontext
3582
3583 with localcontext() as c1:
3584 del c1
3585 n1 = Context(prec=1)
3586 setcontext(n1)
3587 with localcontext(n1) as c2:
3588 del n1
3589 self.assertEqual(c2.prec, 1)
3590 del c2
3591 n2 = Context(prec=2)
3592 setcontext(n2)
3593 del n2
3594 self.assertEqual(getcontext().prec, 2)
3595 n3 = Context(prec=3)
3596 setcontext(n3)
3597 self.assertEqual(getcontext().prec, 3)
3598 with localcontext(n3) as c3:
3599 del n3
3600 self.assertEqual(c3.prec, 3)
3601 del c3
3602 n4 = Context(prec=4)
3603 setcontext(n4)
3604 del n4
3605 self.assertEqual(getcontext().prec, 4)
3606 with localcontext() as c4:
3607 self.assertEqual(c4.prec, 4)
3608 del c4
3609
3610class CContextWithStatement(ContextWithStatement):
3611 decimal = C
3612class PyContextWithStatement(ContextWithStatement):
3613 decimal = P
3614
3615class ContextFlags(unittest.TestCase):
3616
3617 def test_flags_irrelevant(self):
3618 # check that the result (numeric result + flags raised) of an
3619 # arithmetic operation doesn't depend on the current flags
3620 Decimal = self.decimal.Decimal
3621 Context = self.decimal.Context
3622 Inexact = self.decimal.Inexact
3623 Rounded = self.decimal.Rounded
3624 Underflow = self.decimal.Underflow
3625 Clamped = self.decimal.Clamped
3626 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003627
3628 def raise_error(context, flag):
3629 if self.decimal == C:
3630 context.flags[flag] = True
3631 if context.traps[flag]:
3632 raise flag
3633 else:
3634 context._raise_error(flag)
3635
3636 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3637 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3638
3639 # operations that raise various flags, in the form (function, arglist)
3640 operations = [
3641 (context._apply, [Decimal("100E-425000010")]),
3642 (context.sqrt, [Decimal(2)]),
3643 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3644 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3645 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3646 ]
3647
3648 # try various flags individually, then a whole lot at once
3649 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3650 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3651
3652 for fn, args in operations:
3653 # find answer and flags raised using a clean context
3654 context.clear_flags()
3655 ans = fn(*args)
3656 flags = [k for k, v in context.flags.items() if v]
3657
3658 for extra_flags in flagsets:
3659 # set flags, before calling operation
3660 context.clear_flags()
3661 for flag in extra_flags:
3662 raise_error(context, flag)
3663 new_ans = fn(*args)
3664
3665 # flags that we expect to be set after the operation
3666 expected_flags = list(flags)
3667 for flag in extra_flags:
3668 if flag not in expected_flags:
3669 expected_flags.append(flag)
3670 expected_flags.sort(key=id)
3671
3672 # flags we actually got
3673 new_flags = [k for k,v in context.flags.items() if v]
3674 new_flags.sort(key=id)
3675
3676 self.assertEqual(ans, new_ans,
3677 "operation produces different answers depending on flags set: " +
3678 "expected %s, got %s." % (ans, new_ans))
3679 self.assertEqual(new_flags, expected_flags,
3680 "operation raises different flags depending on flags set: " +
3681 "expected %s, got %s" % (expected_flags, new_flags))
3682
3683 def test_flag_comparisons(self):
3684 Context = self.decimal.Context
3685 Inexact = self.decimal.Inexact
3686 Rounded = self.decimal.Rounded
3687
3688 c = Context()
3689
3690 # Valid SignalDict
3691 self.assertNotEqual(c.flags, c.traps)
3692 self.assertNotEqual(c.traps, c.flags)
3693
3694 c.flags = c.traps
3695 self.assertEqual(c.flags, c.traps)
3696 self.assertEqual(c.traps, c.flags)
3697
3698 c.flags[Rounded] = True
3699 c.traps = c.flags
3700 self.assertEqual(c.flags, c.traps)
3701 self.assertEqual(c.traps, c.flags)
3702
3703 d = {}
3704 d.update(c.flags)
3705 self.assertEqual(d, c.flags)
3706 self.assertEqual(c.flags, d)
3707
3708 d[Inexact] = True
3709 self.assertNotEqual(d, c.flags)
3710 self.assertNotEqual(c.flags, d)
3711
3712 # Invalid SignalDict
3713 d = {Inexact:False}
3714 self.assertNotEqual(d, c.flags)
3715 self.assertNotEqual(c.flags, d)
3716
3717 d = ["xyz"]
3718 self.assertNotEqual(d, c.flags)
3719 self.assertNotEqual(c.flags, d)
3720
3721 @requires_IEEE_754
3722 def test_float_operation(self):
3723 Decimal = self.decimal.Decimal
3724 FloatOperation = self.decimal.FloatOperation
3725 localcontext = self.decimal.localcontext
3726
3727 with localcontext() as c:
3728 ##### trap is off by default
3729 self.assertFalse(c.traps[FloatOperation])
3730
3731 # implicit conversion sets the flag
3732 c.clear_flags()
3733 self.assertEqual(Decimal(7.5), 7.5)
3734 self.assertTrue(c.flags[FloatOperation])
3735
3736 c.clear_flags()
3737 self.assertEqual(c.create_decimal(7.5), 7.5)
3738 self.assertTrue(c.flags[FloatOperation])
3739
3740 # explicit conversion does not set the flag
3741 c.clear_flags()
3742 x = Decimal.from_float(7.5)
3743 self.assertFalse(c.flags[FloatOperation])
3744 # comparison sets the flag
3745 self.assertEqual(x, 7.5)
3746 self.assertTrue(c.flags[FloatOperation])
3747
3748 c.clear_flags()
3749 x = c.create_decimal_from_float(7.5)
3750 self.assertFalse(c.flags[FloatOperation])
3751 self.assertEqual(x, 7.5)
3752 self.assertTrue(c.flags[FloatOperation])
3753
3754 ##### set the trap
3755 c.traps[FloatOperation] = True
3756
3757 # implicit conversion raises
3758 c.clear_flags()
3759 self.assertRaises(FloatOperation, Decimal, 7.5)
3760 self.assertTrue(c.flags[FloatOperation])
3761
3762 c.clear_flags()
3763 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3764 self.assertTrue(c.flags[FloatOperation])
3765
3766 # explicit conversion is silent
3767 c.clear_flags()
3768 x = Decimal.from_float(7.5)
3769 self.assertFalse(c.flags[FloatOperation])
3770
3771 c.clear_flags()
3772 x = c.create_decimal_from_float(7.5)
3773 self.assertFalse(c.flags[FloatOperation])
3774
3775 def test_float_comparison(self):
3776 Decimal = self.decimal.Decimal
3777 Context = self.decimal.Context
3778 FloatOperation = self.decimal.FloatOperation
3779 localcontext = self.decimal.localcontext
3780
3781 def assert_attr(a, b, attr, context, signal=None):
3782 context.clear_flags()
3783 f = getattr(a, attr)
3784 if signal == FloatOperation:
3785 self.assertRaises(signal, f, b)
3786 else:
3787 self.assertIs(f(b), True)
3788 self.assertTrue(context.flags[FloatOperation])
3789
3790 small_d = Decimal('0.25')
3791 big_d = Decimal('3.0')
3792 small_f = 0.25
3793 big_f = 3.0
3794
3795 zero_d = Decimal('0.0')
3796 neg_zero_d = Decimal('-0.0')
3797 zero_f = 0.0
3798 neg_zero_f = -0.0
3799
3800 inf_d = Decimal('Infinity')
3801 neg_inf_d = Decimal('-Infinity')
3802 inf_f = float('inf')
3803 neg_inf_f = float('-inf')
3804
3805 def doit(c, signal=None):
3806 # Order
3807 for attr in '__lt__', '__le__':
3808 assert_attr(small_d, big_f, attr, c, signal)
3809
3810 for attr in '__gt__', '__ge__':
3811 assert_attr(big_d, small_f, attr, c, signal)
3812
3813 # Equality
3814 assert_attr(small_d, small_f, '__eq__', c, None)
3815
3816 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3817 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3818
3819 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3820 assert_attr(zero_d, zero_f, '__eq__', c, None)
3821
3822 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3823 assert_attr(inf_d, inf_f, '__eq__', c, None)
3824
3825 # Inequality
3826 assert_attr(small_d, big_f, '__ne__', c, None)
3827
3828 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3829
3830 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3831 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3832
3833 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3834
3835 def test_containers(c, signal=None):
3836 c.clear_flags()
3837 s = set([100.0, Decimal('100.0')])
3838 self.assertEqual(len(s), 1)
3839 self.assertTrue(c.flags[FloatOperation])
3840
3841 c.clear_flags()
3842 if signal:
3843 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3844 else:
3845 s = sorted([10.0, Decimal('10.0')])
3846 self.assertTrue(c.flags[FloatOperation])
3847
3848 c.clear_flags()
3849 b = 10.0 in [Decimal('10.0'), 1.0]
3850 self.assertTrue(c.flags[FloatOperation])
3851
3852 c.clear_flags()
3853 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3854 self.assertTrue(c.flags[FloatOperation])
3855
3856 nc = Context()
3857 with localcontext(nc) as c:
3858 self.assertFalse(c.traps[FloatOperation])
3859 doit(c, signal=None)
3860 test_containers(c, signal=None)
3861
3862 c.traps[FloatOperation] = True
3863 doit(c, signal=FloatOperation)
3864 test_containers(c, signal=FloatOperation)
3865
3866 def test_float_operation_default(self):
3867 Decimal = self.decimal.Decimal
3868 Context = self.decimal.Context
3869 Inexact = self.decimal.Inexact
3870 FloatOperation= self.decimal.FloatOperation
3871
3872 context = Context()
3873 self.assertFalse(context.flags[FloatOperation])
3874 self.assertFalse(context.traps[FloatOperation])
3875
3876 context.clear_traps()
3877 context.traps[Inexact] = True
3878 context.traps[FloatOperation] = True
3879 self.assertTrue(context.traps[FloatOperation])
3880 self.assertTrue(context.traps[Inexact])
3881
3882class CContextFlags(ContextFlags):
3883 decimal = C
3884class PyContextFlags(ContextFlags):
3885 decimal = P
3886
3887class SpecialContexts(unittest.TestCase):
3888 """Test the context templates."""
3889
3890 def test_context_templates(self):
3891 BasicContext = self.decimal.BasicContext
3892 ExtendedContext = self.decimal.ExtendedContext
3893 getcontext = self.decimal.getcontext
3894 setcontext = self.decimal.setcontext
3895 InvalidOperation = self.decimal.InvalidOperation
3896 DivisionByZero = self.decimal.DivisionByZero
3897 Overflow = self.decimal.Overflow
3898 Underflow = self.decimal.Underflow
3899 Clamped = self.decimal.Clamped
3900
3901 assert_signals(self, BasicContext, 'traps',
3902 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3903 )
3904
3905 savecontext = getcontext().copy()
3906 basic_context_prec = BasicContext.prec
3907 extended_context_prec = ExtendedContext.prec
3908
3909 ex = None
3910 try:
3911 BasicContext.prec = ExtendedContext.prec = 441
3912 for template in BasicContext, ExtendedContext:
3913 setcontext(template)
3914 c = getcontext()
3915 self.assertIsNot(c, template)
3916 self.assertEqual(c.prec, 441)
3917 except Exception as e:
3918 ex = e.__class__
3919 finally:
3920 BasicContext.prec = basic_context_prec
3921 ExtendedContext.prec = extended_context_prec
3922 setcontext(savecontext)
3923 if ex:
3924 raise ex
3925
3926 def test_default_context(self):
3927 DefaultContext = self.decimal.DefaultContext
3928 BasicContext = self.decimal.BasicContext
3929 ExtendedContext = self.decimal.ExtendedContext
3930 getcontext = self.decimal.getcontext
3931 setcontext = self.decimal.setcontext
3932 InvalidOperation = self.decimal.InvalidOperation
3933 DivisionByZero = self.decimal.DivisionByZero
3934 Overflow = self.decimal.Overflow
3935
3936 self.assertEqual(BasicContext.prec, 9)
3937 self.assertEqual(ExtendedContext.prec, 9)
3938
3939 assert_signals(self, DefaultContext, 'traps',
3940 [InvalidOperation, DivisionByZero, Overflow]
3941 )
3942
3943 savecontext = getcontext().copy()
3944 default_context_prec = DefaultContext.prec
3945
3946 ex = None
3947 try:
3948 c = getcontext()
3949 saveprec = c.prec
3950
3951 DefaultContext.prec = 961
3952 c = getcontext()
3953 self.assertEqual(c.prec, saveprec)
3954
3955 setcontext(DefaultContext)
3956 c = getcontext()
3957 self.assertIsNot(c, DefaultContext)
3958 self.assertEqual(c.prec, 961)
3959 except Exception as e:
3960 ex = e.__class__
3961 finally:
3962 DefaultContext.prec = default_context_prec
3963 setcontext(savecontext)
3964 if ex:
3965 raise ex
3966
3967class CSpecialContexts(SpecialContexts):
3968 decimal = C
3969class PySpecialContexts(SpecialContexts):
3970 decimal = P
3971
3972class ContextInputValidation(unittest.TestCase):
3973
3974 def test_invalid_context(self):
3975 Context = self.decimal.Context
3976 DefaultContext = self.decimal.DefaultContext
3977
3978 c = DefaultContext.copy()
3979
3980 # prec, Emax
3981 for attr in ['prec', 'Emax']:
3982 setattr(c, attr, 999999)
3983 self.assertEqual(getattr(c, attr), 999999)
3984 self.assertRaises(ValueError, setattr, c, attr, -1)
3985 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3986
3987 # Emin
3988 setattr(c, 'Emin', -999999)
3989 self.assertEqual(getattr(c, 'Emin'), -999999)
3990 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3991 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3992
Stefan Krah1919b7e2012-03-21 18:25:23 +01003993 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3994 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3995 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3996 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3997
3998 # capitals, clamp
3999 for attr in ['capitals', 'clamp']:
4000 self.assertRaises(ValueError, setattr, c, attr, -1)
4001 self.assertRaises(ValueError, setattr, c, attr, 2)
4002 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4003
4004 # Invalid attribute
4005 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4006
4007 # Invalid signal dict
4008 self.assertRaises(TypeError, setattr, c, 'flags', [])
4009 self.assertRaises(KeyError, setattr, c, 'flags', {})
4010 self.assertRaises(KeyError, setattr, c, 'traps',
4011 {'InvalidOperation':0})
4012
4013 # Attributes cannot be deleted
4014 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4015 'flags', 'traps']:
4016 self.assertRaises(AttributeError, c.__delattr__, attr)
4017
4018 # Invalid attributes
4019 self.assertRaises(TypeError, getattr, c, 9)
4020 self.assertRaises(TypeError, setattr, c, 9)
4021
4022 # Invalid values in constructor
4023 self.assertRaises(TypeError, Context, rounding=999999)
4024 self.assertRaises(TypeError, Context, rounding='xyz')
4025 self.assertRaises(ValueError, Context, clamp=2)
4026 self.assertRaises(ValueError, Context, capitals=-1)
4027 self.assertRaises(KeyError, Context, flags=["P"])
4028 self.assertRaises(KeyError, Context, traps=["Q"])
4029
4030 # Type error in conversion
4031 self.assertRaises(TypeError, Context, flags=(0,1))
4032 self.assertRaises(TypeError, Context, traps=(1,0))
4033
4034class CContextInputValidation(ContextInputValidation):
4035 decimal = C
4036class PyContextInputValidation(ContextInputValidation):
4037 decimal = P
4038
4039class ContextSubclassing(unittest.TestCase):
4040
4041 def test_context_subclassing(self):
4042 decimal = self.decimal
4043 Decimal = decimal.Decimal
4044 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004045 Clamped = decimal.Clamped
4046 DivisionByZero = decimal.DivisionByZero
4047 Inexact = decimal.Inexact
4048 Overflow = decimal.Overflow
4049 Rounded = decimal.Rounded
4050 Subnormal = decimal.Subnormal
4051 Underflow = decimal.Underflow
4052 InvalidOperation = decimal.InvalidOperation
4053
4054 class MyContext(Context):
4055 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4056 capitals=None, clamp=None, flags=None,
4057 traps=None):
4058 Context.__init__(self)
4059 if prec is not None:
4060 self.prec = prec
4061 if rounding is not None:
4062 self.rounding = rounding
4063 if Emin is not None:
4064 self.Emin = Emin
4065 if Emax is not None:
4066 self.Emax = Emax
4067 if capitals is not None:
4068 self.capitals = capitals
4069 if clamp is not None:
4070 self.clamp = clamp
4071 if flags is not None:
4072 if isinstance(flags, list):
4073 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4074 self.flags = flags
4075 if traps is not None:
4076 if isinstance(traps, list):
4077 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4078 self.traps = traps
4079
4080 c = Context()
4081 d = MyContext()
4082 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4083 'flags', 'traps'):
4084 self.assertEqual(getattr(c, attr), getattr(d, attr))
4085
4086 # prec
4087 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4088 c = MyContext(prec=1)
4089 self.assertEqual(c.prec, 1)
4090 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4091
4092 # rounding
4093 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4094 c = MyContext(rounding=ROUND_DOWN, prec=1)
4095 self.assertEqual(c.rounding, ROUND_DOWN)
4096 self.assertEqual(c.plus(Decimal('9.9')), 9)
4097
4098 # Emin
4099 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4100 c = MyContext(Emin=-1, prec=1)
4101 self.assertEqual(c.Emin, -1)
4102 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4103 self.assertEqual(x, Decimal('0.0'))
4104 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4105 self.assertTrue(c.flags[signal])
4106
4107 # Emax
4108 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4109 c = MyContext(Emax=1, prec=1)
4110 self.assertEqual(c.Emax, 1)
4111 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4112 if self.decimal == C:
4113 for signal in (Inexact, Overflow, Rounded):
4114 self.assertTrue(c.flags[signal])
4115
4116 # capitals
4117 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4118 c = MyContext(capitals=0)
4119 self.assertEqual(c.capitals, 0)
4120 x = c.create_decimal('1E222')
4121 self.assertEqual(c.to_sci_string(x), '1e+222')
4122
4123 # clamp
4124 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4125 c = MyContext(clamp=1, Emax=99)
4126 self.assertEqual(c.clamp, 1)
4127 x = c.plus(Decimal('1e99'))
4128 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4129
4130 # flags
4131 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4132 c = MyContext(flags=[Rounded, DivisionByZero])
4133 for signal in (Rounded, DivisionByZero):
4134 self.assertTrue(c.flags[signal])
4135 c.clear_flags()
4136 for signal in OrderedSignals[decimal]:
4137 self.assertFalse(c.flags[signal])
4138
4139 # traps
4140 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4141 c = MyContext(traps=[Rounded, DivisionByZero])
4142 for signal in (Rounded, DivisionByZero):
4143 self.assertTrue(c.traps[signal])
4144 c.clear_traps()
4145 for signal in OrderedSignals[decimal]:
4146 self.assertFalse(c.traps[signal])
4147
4148class CContextSubclassing(ContextSubclassing):
4149 decimal = C
4150class PyContextSubclassing(ContextSubclassing):
4151 decimal = P
4152
4153@skip_if_extra_functionality
4154class CheckAttributes(unittest.TestCase):
4155
4156 def test_module_attributes(self):
4157
4158 # Architecture dependent context limits
4159 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4160 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4161 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4162 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4163
4164 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4165 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4166
4167 self.assertEqual(C.__version__, P.__version__)
Stefan Krah45059eb2013-11-24 19:44:57 +01004168 self.assertEqual(C.__libmpdec_version__, P.__libmpdec_version__)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004169
4170 x = dir(C)
4171 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02004172 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004173
4174 def test_context_attributes(self):
4175
4176 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4177 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4178 self.assertEqual(set(x) - set(y), set())
4179
4180 def test_decimal_attributes(self):
4181
4182 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4183 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4184 self.assertEqual(set(x) - set(y), set())
4185
4186class Coverage(unittest.TestCase):
4187
4188 def test_adjusted(self):
4189 Decimal = self.decimal.Decimal
4190
4191 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4192 # XXX raise?
4193 self.assertEqual(Decimal('nan').adjusted(), 0)
4194 self.assertEqual(Decimal('inf').adjusted(), 0)
4195
4196 def test_canonical(self):
4197 Decimal = self.decimal.Decimal
4198 getcontext = self.decimal.getcontext
4199
4200 x = Decimal(9).canonical()
4201 self.assertEqual(x, 9)
4202
4203 c = getcontext()
4204 x = c.canonical(Decimal(9))
4205 self.assertEqual(x, 9)
4206
4207 def test_context_repr(self):
4208 c = self.decimal.DefaultContext.copy()
4209
4210 c.prec = 425000000
4211 c.Emax = 425000000
4212 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004213 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004214 c.capitals = 0
4215 c.clamp = 1
4216 for sig in OrderedSignals[self.decimal]:
4217 c.flags[sig] = False
4218 c.traps[sig] = False
4219
4220 s = c.__repr__()
4221 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4222 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4223 "flags=[], traps=[])"
4224 self.assertEqual(s, t)
4225
4226 def test_implicit_context(self):
4227 Decimal = self.decimal.Decimal
4228 localcontext = self.decimal.localcontext
4229
4230 with localcontext() as c:
4231 c.prec = 1
4232 c.Emax = 1
4233 c.Emin = -1
4234
4235 # abs
4236 self.assertEqual(abs(Decimal("-10")), 10)
4237 # add
4238 self.assertEqual(Decimal("7") + 1, 8)
4239 # divide
4240 self.assertEqual(Decimal("10") / 5, 2)
4241 # divide_int
4242 self.assertEqual(Decimal("10") // 7, 1)
4243 # fma
4244 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4245 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4246 # three arg power
4247 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4248 # exp
4249 self.assertEqual(Decimal("1.01").exp(), 3)
4250 # is_normal
4251 self.assertIs(Decimal("0.01").is_normal(), False)
4252 # is_subnormal
4253 self.assertIs(Decimal("0.01").is_subnormal(), True)
4254 # ln
4255 self.assertEqual(Decimal("20").ln(), 3)
4256 # log10
4257 self.assertEqual(Decimal("20").log10(), 1)
4258 # logb
4259 self.assertEqual(Decimal("580").logb(), 2)
4260 # logical_invert
4261 self.assertEqual(Decimal("10").logical_invert(), 1)
4262 # minus
4263 self.assertEqual(-Decimal("-10"), 10)
4264 # multiply
4265 self.assertEqual(Decimal("2") * 4, 8)
4266 # next_minus
4267 self.assertEqual(Decimal("10").next_minus(), 9)
4268 # next_plus
4269 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4270 # normalize
4271 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4272 # number_class
4273 self.assertEqual(Decimal("10").number_class(), '+Normal')
4274 # plus
4275 self.assertEqual(+Decimal("-1"), -1)
4276 # remainder
4277 self.assertEqual(Decimal("10") % 7, 3)
4278 # subtract
4279 self.assertEqual(Decimal("10") - 7, 3)
4280 # to_integral_exact
4281 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4282
4283 # Boolean functions
4284 self.assertTrue(Decimal("1").is_canonical())
4285 self.assertTrue(Decimal("1").is_finite())
4286 self.assertTrue(Decimal("1").is_finite())
4287 self.assertTrue(Decimal("snan").is_snan())
4288 self.assertTrue(Decimal("-1").is_signed())
4289 self.assertTrue(Decimal("0").is_zero())
4290 self.assertTrue(Decimal("0").is_zero())
4291
4292 # Copy
4293 with localcontext() as c:
4294 c.prec = 10000
4295 x = 1228 ** 1523
4296 y = -Decimal(x)
4297
4298 z = y.copy_abs()
4299 self.assertEqual(z, x)
4300
4301 z = y.copy_negate()
4302 self.assertEqual(z, x)
4303
4304 z = y.copy_sign(Decimal(1))
4305 self.assertEqual(z, x)
4306
4307 def test_divmod(self):
4308 Decimal = self.decimal.Decimal
4309 localcontext = self.decimal.localcontext
4310 InvalidOperation = self.decimal.InvalidOperation
4311 DivisionByZero = self.decimal.DivisionByZero
4312
4313 with localcontext() as c:
4314 q, r = divmod(Decimal("10912837129"), 1001)
4315 self.assertEqual(q, Decimal('10901935'))
4316 self.assertEqual(r, Decimal('194'))
4317
4318 q, r = divmod(Decimal("NaN"), 7)
4319 self.assertTrue(q.is_nan() and r.is_nan())
4320
4321 c.traps[InvalidOperation] = False
4322 q, r = divmod(Decimal("NaN"), 7)
4323 self.assertTrue(q.is_nan() and r.is_nan())
4324
4325 c.traps[InvalidOperation] = False
4326 c.clear_flags()
4327 q, r = divmod(Decimal("inf"), Decimal("inf"))
4328 self.assertTrue(q.is_nan() and r.is_nan())
4329 self.assertTrue(c.flags[InvalidOperation])
4330
4331 c.clear_flags()
4332 q, r = divmod(Decimal("inf"), 101)
4333 self.assertTrue(q.is_infinite() and r.is_nan())
4334 self.assertTrue(c.flags[InvalidOperation])
4335
4336 c.clear_flags()
4337 q, r = divmod(Decimal(0), 0)
4338 self.assertTrue(q.is_nan() and r.is_nan())
4339 self.assertTrue(c.flags[InvalidOperation])
4340
4341 c.traps[DivisionByZero] = False
4342 c.clear_flags()
4343 q, r = divmod(Decimal(11), 0)
4344 self.assertTrue(q.is_infinite() and r.is_nan())
4345 self.assertTrue(c.flags[InvalidOperation] and
4346 c.flags[DivisionByZero])
4347
4348 def test_power(self):
4349 Decimal = self.decimal.Decimal
4350 localcontext = self.decimal.localcontext
4351 Overflow = self.decimal.Overflow
4352 Rounded = self.decimal.Rounded
4353
4354 with localcontext() as c:
4355 c.prec = 3
4356 c.clear_flags()
4357 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4358 self.assertTrue(c.flags[Rounded])
4359
4360 c.prec = 1
4361 c.Emax = 1
4362 c.Emin = -1
4363 c.clear_flags()
4364 c.traps[Overflow] = False
4365 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4366 self.assertTrue(c.flags[Overflow])
4367
4368 def test_quantize(self):
4369 Decimal = self.decimal.Decimal
4370 localcontext = self.decimal.localcontext
4371 InvalidOperation = self.decimal.InvalidOperation
4372
4373 with localcontext() as c:
4374 c.prec = 1
4375 c.Emax = 1
4376 c.Emin = -1
4377 c.traps[InvalidOperation] = False
4378 x = Decimal(99).quantize(Decimal("1e1"))
4379 self.assertTrue(x.is_nan())
4380
4381 def test_radix(self):
4382 Decimal = self.decimal.Decimal
4383 getcontext = self.decimal.getcontext
4384
4385 c = getcontext()
4386 self.assertEqual(Decimal("1").radix(), 10)
4387 self.assertEqual(c.radix(), 10)
4388
4389 def test_rop(self):
4390 Decimal = self.decimal.Decimal
4391
4392 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4393 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4394 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4395
4396 def test_round(self):
4397 # Python3 behavior: round() returns Decimal
4398 Decimal = self.decimal.Decimal
4399 getcontext = self.decimal.getcontext
4400
4401 c = getcontext()
4402 c.prec = 28
4403
4404 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4405 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4406 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4407 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4408 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4409
4410 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4411 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4412
4413 def test_create_decimal(self):
4414 c = self.decimal.Context()
4415 self.assertRaises(ValueError, c.create_decimal, ["%"])
4416
4417 def test_int(self):
4418 Decimal = self.decimal.Decimal
4419 localcontext = self.decimal.localcontext
4420
4421 with localcontext() as c:
4422 c.prec = 9999
4423 x = Decimal(1221**1271) / 10**3923
4424 self.assertEqual(int(x), 1)
4425 self.assertEqual(x.to_integral(), 2)
4426
4427 def test_copy(self):
4428 Context = self.decimal.Context
4429
4430 c = Context()
4431 c.prec = 10000
4432 x = -(1172 ** 1712)
4433
4434 y = c.copy_abs(x)
4435 self.assertEqual(y, -x)
4436
4437 y = c.copy_negate(x)
4438 self.assertEqual(y, -x)
4439
4440 y = c.copy_sign(x, 1)
4441 self.assertEqual(y, -x)
4442
4443class CCoverage(Coverage):
4444 decimal = C
4445class PyCoverage(Coverage):
4446 decimal = P
4447
4448class PyFunctionality(unittest.TestCase):
4449 """Extra functionality in decimal.py"""
4450
4451 def test_py_quantize_watchexp(self):
4452 # watchexp functionality
4453 Decimal = P.Decimal
4454 localcontext = P.localcontext
4455
4456 with localcontext() as c:
4457 c.prec = 1
4458 c.Emax = 1
4459 c.Emin = -1
4460 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4461 self.assertEqual(x, Decimal('1.00E+5'))
4462
4463 def test_py_alternate_formatting(self):
4464 # triples giving a format, a Decimal, and the expected result
4465 Decimal = P.Decimal
4466 localcontext = P.localcontext
4467
4468 test_values = [
4469 # Issue 7094: Alternate formatting (specified by #)
4470 ('.0e', '1.0', '1e+0'),
4471 ('#.0e', '1.0', '1.e+0'),
4472 ('.0f', '1.0', '1'),
4473 ('#.0f', '1.0', '1.'),
4474 ('g', '1.1', '1.1'),
4475 ('#g', '1.1', '1.1'),
4476 ('.0g', '1', '1'),
4477 ('#.0g', '1', '1.'),
4478 ('.0%', '1.0', '100%'),
4479 ('#.0%', '1.0', '100.%'),
4480 ]
4481 for fmt, d, result in test_values:
4482 self.assertEqual(format(Decimal(d), fmt), result)
4483
4484class PyWhitebox(unittest.TestCase):
4485 """White box testing for decimal.py"""
4486
4487 def test_py_exact_power(self):
4488 # Rarely exercised lines in _power_exact.
4489 Decimal = P.Decimal
4490 localcontext = P.localcontext
4491
4492 with localcontext() as c:
4493 c.prec = 8
4494 x = Decimal(2**16) ** Decimal("-0.5")
4495 self.assertEqual(x, Decimal('0.00390625'))
4496
4497 x = Decimal(2**16) ** Decimal("-0.6")
4498 self.assertEqual(x, Decimal('0.0012885819'))
4499
4500 x = Decimal("256e7") ** Decimal("-0.5")
4501
4502 x = Decimal(152587890625) ** Decimal('-0.0625')
4503 self.assertEqual(x, Decimal("0.2"))
4504
4505 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4506
4507 x = Decimal(5**2659) ** Decimal('-0.0625')
4508
4509 c.prec = 1
4510 x = Decimal("152587890625") ** Decimal('-0.5')
4511 c.prec = 201
4512 x = Decimal(2**578) ** Decimal("-0.5")
4513
4514 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004515 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004516 Decimal = P.Decimal
4517 DefaultContext = P.DefaultContext
4518 setcontext = P.setcontext
4519
4520 c = DefaultContext.copy()
4521 c.traps = dict((s, 0) for s in OrderedSignals[P])
4522 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004523
4524 d1 = Decimal('-25e55')
4525 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004526 d2 = Decimal('33e+33')
4527 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004528
4529 def checkSameDec(operation, useOther=False):
4530 if useOther:
4531 eval("d1." + operation + "(d2)")
4532 self.assertEqual(d1._sign, b1._sign)
4533 self.assertEqual(d1._int, b1._int)
4534 self.assertEqual(d1._exp, b1._exp)
4535 self.assertEqual(d2._sign, b2._sign)
4536 self.assertEqual(d2._int, b2._int)
4537 self.assertEqual(d2._exp, b2._exp)
4538 else:
4539 eval("d1." + operation + "()")
4540 self.assertEqual(d1._sign, b1._sign)
4541 self.assertEqual(d1._int, b1._int)
4542 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004543
4544 Decimal(d1)
4545 self.assertEqual(d1._sign, b1._sign)
4546 self.assertEqual(d1._int, b1._int)
4547 self.assertEqual(d1._exp, b1._exp)
4548
4549 checkSameDec("__abs__")
4550 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004551 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004552 checkSameDec("__eq__", True)
4553 checkSameDec("__ne__", True)
4554 checkSameDec("__le__", True)
4555 checkSameDec("__lt__", True)
4556 checkSameDec("__ge__", True)
4557 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004558 checkSameDec("__float__")
4559 checkSameDec("__floordiv__", True)
4560 checkSameDec("__hash__")
4561 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004562 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004563 checkSameDec("__mod__", True)
4564 checkSameDec("__mul__", True)
4565 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004566 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004567 checkSameDec("__pos__")
4568 checkSameDec("__pow__", True)
4569 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004570 checkSameDec("__rdivmod__", True)
4571 checkSameDec("__repr__")
4572 checkSameDec("__rfloordiv__", True)
4573 checkSameDec("__rmod__", True)
4574 checkSameDec("__rmul__", True)
4575 checkSameDec("__rpow__", True)
4576 checkSameDec("__rsub__", True)
4577 checkSameDec("__str__")
4578 checkSameDec("__sub__", True)
4579 checkSameDec("__truediv__", True)
4580 checkSameDec("adjusted")
4581 checkSameDec("as_tuple")
4582 checkSameDec("compare", True)
4583 checkSameDec("max", True)
4584 checkSameDec("min", True)
4585 checkSameDec("normalize")
4586 checkSameDec("quantize", True)
4587 checkSameDec("remainder_near", True)
4588 checkSameDec("same_quantum", True)
4589 checkSameDec("sqrt")
4590 checkSameDec("to_eng_string")
4591 checkSameDec("to_integral")
4592
Stefan Krah1919b7e2012-03-21 18:25:23 +01004593 def test_py_decimal_id(self):
4594 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004595
Stefan Krah1919b7e2012-03-21 18:25:23 +01004596 d = Decimal(45)
4597 e = Decimal(d)
4598 self.assertEqual(str(e), '45')
4599 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004600
Stefan Krah1919b7e2012-03-21 18:25:23 +01004601 def test_py_rescale(self):
4602 # Coverage
4603 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004604 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004605
Stefan Krah1919b7e2012-03-21 18:25:23 +01004606 with localcontext() as c:
4607 x = Decimal("NaN")._rescale(3, ROUND_UP)
4608 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004609
Stefan Krah1919b7e2012-03-21 18:25:23 +01004610 def test_py__round(self):
4611 # Coverage
4612 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004613
Stefan Krah1919b7e2012-03-21 18:25:23 +01004614 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004615
Stefan Krah1919b7e2012-03-21 18:25:23 +01004616class CFunctionality(unittest.TestCase):
4617 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004618
Stefan Krah1919b7e2012-03-21 18:25:23 +01004619 @requires_extra_functionality
4620 def test_c_ieee_context(self):
4621 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4622 IEEEContext = C.IEEEContext
4623 DECIMAL32 = C.DECIMAL32
4624 DECIMAL64 = C.DECIMAL64
4625 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004626
Stefan Krah1919b7e2012-03-21 18:25:23 +01004627 def assert_rest(self, context):
4628 self.assertEqual(context.clamp, 1)
4629 assert_signals(self, context, 'traps', [])
4630 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004631
Stefan Krah1919b7e2012-03-21 18:25:23 +01004632 c = IEEEContext(DECIMAL32)
4633 self.assertEqual(c.prec, 7)
4634 self.assertEqual(c.Emax, 96)
4635 self.assertEqual(c.Emin, -95)
4636 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004637
Stefan Krah1919b7e2012-03-21 18:25:23 +01004638 c = IEEEContext(DECIMAL64)
4639 self.assertEqual(c.prec, 16)
4640 self.assertEqual(c.Emax, 384)
4641 self.assertEqual(c.Emin, -383)
4642 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004643
Stefan Krah1919b7e2012-03-21 18:25:23 +01004644 c = IEEEContext(DECIMAL128)
4645 self.assertEqual(c.prec, 34)
4646 self.assertEqual(c.Emax, 6144)
4647 self.assertEqual(c.Emin, -6143)
4648 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004649
Stefan Krah1919b7e2012-03-21 18:25:23 +01004650 # Invalid values
4651 self.assertRaises(OverflowError, IEEEContext, 2**63)
4652 self.assertRaises(ValueError, IEEEContext, -1)
4653 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004654
Stefan Krah1919b7e2012-03-21 18:25:23 +01004655 @requires_extra_functionality
4656 def test_c_context(self):
4657 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004658
Stefan Krah1919b7e2012-03-21 18:25:23 +01004659 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4660 self.assertEqual(c._flags, C.DecClamped)
4661 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004662
Stefan Krah1919b7e2012-03-21 18:25:23 +01004663 @requires_extra_functionality
4664 def test_constants(self):
4665 # Condition flags
4666 cond = (
4667 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4668 C.DecDivisionImpossible, C.DecDivisionUndefined,
4669 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4670 C.DecInvalidOperation, C.DecMallocError,
4671 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4672 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004673 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004674
4675 # IEEEContext
4676 self.assertEqual(C.DECIMAL32, 32)
4677 self.assertEqual(C.DECIMAL64, 64)
4678 self.assertEqual(C.DECIMAL128, 128)
4679 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4680
Stefan Krah1919b7e2012-03-21 18:25:23 +01004681 # Conditions
4682 for i, v in enumerate(cond):
4683 self.assertEqual(v, 1<<i)
4684
4685 self.assertEqual(C.DecIEEEInvalidOperation,
4686 C.DecConversionSyntax|
4687 C.DecDivisionImpossible|
4688 C.DecDivisionUndefined|
4689 C.DecFpuError|
4690 C.DecInvalidContext|
4691 C.DecInvalidOperation|
4692 C.DecMallocError)
4693
4694 self.assertEqual(C.DecErrors,
4695 C.DecIEEEInvalidOperation|
4696 C.DecDivisionByZero)
4697
4698 self.assertEqual(C.DecTraps,
4699 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4700
4701class CWhitebox(unittest.TestCase):
4702 """Whitebox testing for _decimal"""
4703
4704 def test_bignum(self):
4705 # Not exactly whitebox, but too slow with pydecimal.
4706
4707 Decimal = C.Decimal
4708 localcontext = C.localcontext
4709
4710 b1 = 10**35
4711 b2 = 10**36
4712 with localcontext() as c:
4713 c.prec = 1000000
4714 for i in range(5):
4715 a = random.randrange(b1, b2)
4716 b = random.randrange(1000, 1200)
4717 x = a ** b
4718 y = Decimal(a) ** Decimal(b)
4719 self.assertEqual(x, y)
4720
4721 def test_invalid_construction(self):
4722 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4723
4724 def test_c_input_restriction(self):
4725 # Too large for _decimal to be converted exactly
4726 Decimal = C.Decimal
4727 InvalidOperation = C.InvalidOperation
4728 Context = C.Context
4729 localcontext = C.localcontext
4730
4731 with localcontext(Context()):
4732 self.assertRaises(InvalidOperation, Decimal,
4733 "1e9999999999999999999")
4734
4735 def test_c_context_repr(self):
4736 # This test is _decimal-only because flags are not printed
4737 # in the same order.
4738 DefaultContext = C.DefaultContext
4739 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004740
4741 c = DefaultContext.copy()
4742
4743 c.prec = 425000000
4744 c.Emax = 425000000
4745 c.Emin = -425000000
4746 c.rounding = ROUND_HALF_DOWN
4747 c.capitals = 0
4748 c.clamp = 1
4749 for sig in OrderedSignals[C]:
4750 c.flags[sig] = True
4751 c.traps[sig] = True
4752 c.flags[FloatOperation] = True
4753 c.traps[FloatOperation] = True
4754
4755 s = c.__repr__()
4756 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4757 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4758 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4759 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4760 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4761 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4762 self.assertEqual(s, t)
4763
4764 def test_c_context_errors(self):
4765 Context = C.Context
4766 InvalidOperation = C.InvalidOperation
4767 Overflow = C.Overflow
4768 FloatOperation = C.FloatOperation
4769 localcontext = C.localcontext
4770 getcontext = C.getcontext
4771 setcontext = C.setcontext
4772 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4773
4774 c = Context()
4775
4776 # SignalDict: input validation
4777 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4778 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4779 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4780 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4781 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4782 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4783 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4784 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4785
4786 # Test assignment from a signal dict with the correct length but
4787 # one invalid key.
4788 d = c.flags.copy()
4789 del d[FloatOperation]
4790 d["XYZ"] = 91283719
4791 self.assertRaises(KeyError, setattr, c, 'flags', d)
4792 self.assertRaises(KeyError, setattr, c, 'traps', d)
4793
4794 # Input corner cases
4795 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4796 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4797
4798 # prec, Emax, Emin
4799 for attr in ['prec', 'Emax']:
4800 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4801 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4802
4803 # prec, Emax, Emin in context constructor
4804 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4805 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4806 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4807
4808 # Overflow in conversion
4809 self.assertRaises(OverflowError, Context, prec=int_max+1)
4810 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4811 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004812 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4813 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4814
4815 # OverflowError, general ValueError
4816 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4817 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4818 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4819 if sys.platform != 'win32':
4820 self.assertRaises(ValueError, setattr, c, attr, int_max)
4821 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4822
Stefan Krah1919b7e2012-03-21 18:25:23 +01004823 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4824 if C.MAX_PREC == 425000000:
4825 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4826 int_max+1)
4827 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4828 int_max+1)
4829 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4830 -int_max-2)
4831
4832 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4833 if C.MAX_PREC == 425000000:
4834 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4835 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4836 1070000001)
4837 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4838 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4839 1070000001)
4840 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4841 -1070000001)
4842 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4843
4844 # capitals, clamp
4845 for attr in ['capitals', 'clamp']:
4846 self.assertRaises(ValueError, setattr, c, attr, -1)
4847 self.assertRaises(ValueError, setattr, c, attr, 2)
4848 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4849 if HAVE_CONFIG_64:
4850 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4851 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4852
4853 # Invalid local context
4854 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4855 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004856 self.assertRaises(TypeError, exec,
4857 'with localcontext(context=getcontext()): pass',
4858 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004859
4860 # setcontext
4861 saved_context = getcontext()
4862 self.assertRaises(TypeError, setcontext, "xyz")
4863 setcontext(saved_context)
4864
Stefan Krah59a4a932013-01-16 12:58:59 +01004865 def test_rounding_strings_interned(self):
4866
4867 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4868 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4869 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4870 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4871 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4872 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4873 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4874 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4875
Stefan Krah1919b7e2012-03-21 18:25:23 +01004876 @requires_extra_functionality
4877 def test_c_context_errors_extra(self):
4878 Context = C.Context
4879 InvalidOperation = C.InvalidOperation
4880 Overflow = C.Overflow
4881 localcontext = C.localcontext
4882 getcontext = C.getcontext
4883 setcontext = C.setcontext
4884 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4885
4886 c = Context()
4887
4888 # Input corner cases
4889 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4890
4891 # OverflowError, general ValueError
4892 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4893 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4894 if sys.platform != 'win32':
4895 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4896 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4897
4898 # OverflowError, general TypeError
4899 for attr in ('_flags', '_traps'):
4900 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4901 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4902 if sys.platform != 'win32':
4903 self.assertRaises(TypeError, setattr, c, attr, int_max)
4904 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4905
4906 # _allcr
4907 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4908 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4909 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4910 if HAVE_CONFIG_64:
4911 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4912 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4913
4914 # _flags, _traps
4915 for attr in ['_flags', '_traps']:
4916 self.assertRaises(TypeError, setattr, c, attr, 999999)
4917 self.assertRaises(TypeError, setattr, c, attr, 'x')
4918
4919 def test_c_valid_context(self):
4920 # These tests are for code coverage in _decimal.
4921 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004922 Clamped = C.Clamped
4923 Underflow = C.Underflow
4924 Inexact = C.Inexact
4925 Rounded = C.Rounded
4926 Subnormal = C.Subnormal
4927
4928 c = DefaultContext.copy()
4929
4930 # Exercise all getters and setters
4931 c.prec = 34
4932 c.rounding = ROUND_HALF_UP
4933 c.Emax = 3000
4934 c.Emin = -3000
4935 c.capitals = 1
4936 c.clamp = 0
4937
4938 self.assertEqual(c.prec, 34)
4939 self.assertEqual(c.rounding, ROUND_HALF_UP)
4940 self.assertEqual(c.Emin, -3000)
4941 self.assertEqual(c.Emax, 3000)
4942 self.assertEqual(c.capitals, 1)
4943 self.assertEqual(c.clamp, 0)
4944
4945 self.assertEqual(c.Etiny(), -3033)
4946 self.assertEqual(c.Etop(), 2967)
4947
4948 # Exercise all unsafe setters
4949 if C.MAX_PREC == 425000000:
4950 c._unsafe_setprec(999999999)
4951 c._unsafe_setemax(999999999)
4952 c._unsafe_setemin(-999999999)
4953 self.assertEqual(c.prec, 999999999)
4954 self.assertEqual(c.Emax, 999999999)
4955 self.assertEqual(c.Emin, -999999999)
4956
4957 @requires_extra_functionality
4958 def test_c_valid_context_extra(self):
4959 DefaultContext = C.DefaultContext
4960
4961 c = DefaultContext.copy()
4962 self.assertEqual(c._allcr, 1)
4963 c._allcr = 0
4964 self.assertEqual(c._allcr, 0)
4965
4966 def test_c_round(self):
4967 # Restricted input.
4968 Decimal = C.Decimal
4969 InvalidOperation = C.InvalidOperation
4970 localcontext = C.localcontext
4971 MAX_EMAX = C.MAX_EMAX
4972 MIN_ETINY = C.MIN_ETINY
4973 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4974
4975 with localcontext() as c:
4976 c.traps[InvalidOperation] = True
4977 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4978 -int_max-1)
4979 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4980 int_max)
4981 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4982 int(MAX_EMAX+1))
4983 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4984 -int(MIN_ETINY-1))
4985 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4986 -int_max-2)
4987 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4988 int_max+1)
4989
4990 def test_c_format(self):
4991 # Restricted input
4992 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004993 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4994
4995 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4996 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4997 self.assertRaises(TypeError, Decimal(1).__format__, [])
4998
Stefan Kraheb8c4512013-01-24 15:22:33 +01004999 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
5000 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
5001 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
5002 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005003
5004 def test_c_integral(self):
5005 Decimal = C.Decimal
5006 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01005007 localcontext = C.localcontext
5008
5009 x = Decimal(10)
5010 self.assertEqual(x.to_integral(), 10)
5011 self.assertRaises(TypeError, x.to_integral, '10')
5012 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5013 self.assertRaises(TypeError, x.to_integral, 10)
5014
5015 self.assertEqual(x.to_integral_value(), 10)
5016 self.assertRaises(TypeError, x.to_integral_value, '10')
5017 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5018 self.assertRaises(TypeError, x.to_integral_value, 10)
5019
5020 self.assertEqual(x.to_integral_exact(), 10)
5021 self.assertRaises(TypeError, x.to_integral_exact, '10')
5022 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5023 self.assertRaises(TypeError, x.to_integral_exact, 10)
5024
5025 with localcontext() as c:
5026 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5027 self.assertEqual(x, Decimal('100000000000000000000000000'))
5028
5029 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5030 self.assertEqual(x, Decimal('100000000000000000000000000'))
5031
5032 c.traps[Inexact] = True
5033 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5034
5035 def test_c_funcs(self):
5036 # Invalid arguments
5037 Decimal = C.Decimal
5038 InvalidOperation = C.InvalidOperation
5039 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005040 getcontext = C.getcontext
5041 localcontext = C.localcontext
5042
5043 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5044
5045 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5046 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5047 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5048
Raymond Hettinger771ed762009-01-03 19:20:32 +00005049 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005050 TypeError,
5051 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005052 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005053 self.assertRaises(
5054 TypeError,
5055 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5056 )
5057 self.assertRaises(
5058 TypeError,
5059 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5060 )
5061 self.assertRaises(
5062 TypeError,
5063 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5064 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005065
Stefan Krah1919b7e2012-03-21 18:25:23 +01005066 with localcontext() as c:
5067 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005068
Stefan Krah1919b7e2012-03-21 18:25:23 +01005069 # Invalid arguments
5070 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5071 self.assertRaises(TypeError, c.canonical, 200)
5072 self.assertRaises(TypeError, c.is_canonical, 200)
5073 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5074 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005075
Stefan Krah1919b7e2012-03-21 18:25:23 +01005076 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5077 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005078
Stefan Krah1919b7e2012-03-21 18:25:23 +01005079 c.traps[DivisionByZero] = True
5080 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5081 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5082 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005083
Stefan Krah1919b7e2012-03-21 18:25:23 +01005084 c.clear_flags()
5085 c.traps[InvalidOperation] = True
5086 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5087 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5088 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005089
Stefan Krah1919b7e2012-03-21 18:25:23 +01005090 c.traps[InvalidOperation] = True
5091 c.prec = 2
5092 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005093
Stefan Krah040e3112012-12-15 22:33:33 +01005094 def test_va_args_exceptions(self):
5095 Decimal = C.Decimal
5096 Context = C.Context
5097
5098 x = Decimal("10001111111")
5099
5100 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5101 'logb', 'logical_invert', 'next_minus', 'next_plus',
5102 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5103 func = getattr(x, attr)
5104 self.assertRaises(TypeError, func, context="x")
5105 self.assertRaises(TypeError, func, "x", context=None)
5106
5107 for attr in ['compare', 'compare_signal', 'logical_and',
5108 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5109 'remainder_near', 'rotate', 'scaleb', 'shift']:
5110 func = getattr(x, attr)
5111 self.assertRaises(TypeError, func, context="x")
5112 self.assertRaises(TypeError, func, "x", context=None)
5113
5114 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5115 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5116 self.assertRaises(TypeError, x.to_integral, [], [])
5117
5118 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5119 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5120 self.assertRaises(TypeError, x.to_integral_value, [], [])
5121
5122 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5123 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5124 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5125
5126 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5127 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5128
5129 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5130 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5131 self.assertRaises(TypeError, x.quantize, 1, [], [])
5132
5133 c = Context()
5134 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5135 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5136 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5137
Stefan Krah1919b7e2012-03-21 18:25:23 +01005138 @requires_extra_functionality
5139 def test_c_context_templates(self):
5140 self.assertEqual(
5141 C.BasicContext._traps,
5142 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5143 C.DecUnderflow|C.DecClamped
5144 )
5145 self.assertEqual(
5146 C.DefaultContext._traps,
5147 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5148 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005149
Stefan Krah1919b7e2012-03-21 18:25:23 +01005150 @requires_extra_functionality
5151 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005152
Stefan Krah1919b7e2012-03-21 18:25:23 +01005153 # SignalDict coverage
5154 Context = C.Context
5155 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005156
Stefan Krah1919b7e2012-03-21 18:25:23 +01005157 InvalidOperation = C.InvalidOperation
5158 DivisionByZero = C.DivisionByZero
5159 Overflow = C.Overflow
5160 Subnormal = C.Subnormal
5161 Underflow = C.Underflow
5162 Rounded = C.Rounded
5163 Inexact = C.Inexact
5164 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005165
Stefan Krah1919b7e2012-03-21 18:25:23 +01005166 DecClamped = C.DecClamped
5167 DecInvalidOperation = C.DecInvalidOperation
5168 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005169
Stefan Krah1919b7e2012-03-21 18:25:23 +01005170 def assertIsExclusivelySet(signal, signal_dict):
5171 for sig in signal_dict:
5172 if sig == signal:
5173 self.assertTrue(signal_dict[sig])
5174 else:
5175 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005176
Stefan Krah1919b7e2012-03-21 18:25:23 +01005177 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005178
Stefan Krah1919b7e2012-03-21 18:25:23 +01005179 # Signal dict methods
5180 self.assertTrue(Overflow in c.traps)
5181 c.clear_traps()
5182 for k in c.traps.keys():
5183 c.traps[k] = True
5184 for v in c.traps.values():
5185 self.assertTrue(v)
5186 c.clear_traps()
5187 for k, v in c.traps.items():
5188 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005189
Stefan Krah1919b7e2012-03-21 18:25:23 +01005190 self.assertFalse(c.flags.get(Overflow))
5191 self.assertIs(c.flags.get("x"), None)
5192 self.assertEqual(c.flags.get("x", "y"), "y")
5193 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005194
Stefan Krah1919b7e2012-03-21 18:25:23 +01005195 self.assertEqual(len(c.flags), len(c.traps))
5196 s = sys.getsizeof(c.flags)
5197 s = sys.getsizeof(c.traps)
5198 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005199
Stefan Krah1919b7e2012-03-21 18:25:23 +01005200 # Set flags/traps.
5201 c.clear_flags()
5202 c._flags = DecClamped
5203 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005204
Stefan Krah1919b7e2012-03-21 18:25:23 +01005205 c.clear_traps()
5206 c._traps = DecInvalidOperation
5207 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005208
Stefan Krah1919b7e2012-03-21 18:25:23 +01005209 # Set flags/traps from dictionary.
5210 c.clear_flags()
5211 d = c.flags.copy()
5212 d[DivisionByZero] = True
5213 c.flags = d
5214 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005215
Stefan Krah1919b7e2012-03-21 18:25:23 +01005216 c.clear_traps()
5217 d = c.traps.copy()
5218 d[Underflow] = True
5219 c.traps = d
5220 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005221
Stefan Krah1919b7e2012-03-21 18:25:23 +01005222 # Random constructors
5223 IntSignals = {
5224 Clamped: C.DecClamped,
5225 Rounded: C.DecRounded,
5226 Inexact: C.DecInexact,
5227 Subnormal: C.DecSubnormal,
5228 Underflow: C.DecUnderflow,
5229 Overflow: C.DecOverflow,
5230 DivisionByZero: C.DecDivisionByZero,
5231 InvalidOperation: C.DecIEEEInvalidOperation
5232 }
5233 IntCond = [
5234 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5235 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5236 C.DecConversionSyntax,
5237 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005238
Stefan Krah1919b7e2012-03-21 18:25:23 +01005239 lim = len(OrderedSignals[C])
5240 for r in range(lim):
5241 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005242 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005243 flags = random.sample(OrderedSignals[C], r)
5244 traps = random.sample(OrderedSignals[C], t)
5245 prec = random.randrange(1, 10000)
5246 emin = random.randrange(-10000, 0)
5247 emax = random.randrange(0, 10000)
5248 clamp = random.randrange(0, 2)
5249 caps = random.randrange(0, 2)
5250 cr = random.randrange(0, 2)
5251 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5252 capitals=caps, clamp=clamp, flags=list(flags),
5253 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005254
Stefan Krah1919b7e2012-03-21 18:25:23 +01005255 self.assertEqual(c.prec, prec)
5256 self.assertEqual(c.rounding, round)
5257 self.assertEqual(c.Emin, emin)
5258 self.assertEqual(c.Emax, emax)
5259 self.assertEqual(c.capitals, caps)
5260 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005261
Stefan Krah1919b7e2012-03-21 18:25:23 +01005262 f = 0
5263 for x in flags:
5264 f |= IntSignals[x]
5265 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005266
Stefan Krah1919b7e2012-03-21 18:25:23 +01005267 f = 0
5268 for x in traps:
5269 f |= IntSignals[x]
5270 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005271
Stefan Krah1919b7e2012-03-21 18:25:23 +01005272 for cond in IntCond:
5273 c._flags = cond
5274 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5275 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005276
Stefan Krah1919b7e2012-03-21 18:25:23 +01005277 for cond in IntCond:
5278 c._traps = cond
5279 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5280 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005281
Stefan Krah1919b7e2012-03-21 18:25:23 +01005282 def test_invalid_override(self):
5283 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005284
Stefan Krah1919b7e2012-03-21 18:25:23 +01005285 try:
5286 from locale import CHAR_MAX
5287 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06005288 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson84230a12010-02-18 14:49:50 +00005289
Stefan Krah1919b7e2012-03-21 18:25:23 +01005290 def make_grouping(lst):
5291 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005292
Stefan Krah1919b7e2012-03-21 18:25:23 +01005293 def get_fmt(x, override=None, fmt='n'):
5294 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005295
Stefan Krah1919b7e2012-03-21 18:25:23 +01005296 invalid_grouping = {
5297 'decimal_point' : ',',
5298 'grouping' : make_grouping([255, 255, 0]),
5299 'thousands_sep' : ','
5300 }
5301 invalid_dot = {
5302 'decimal_point' : 'xxxxx',
5303 'grouping' : make_grouping([3, 3, 0]),
5304 'thousands_sep' : ','
5305 }
5306 invalid_sep = {
5307 'decimal_point' : '.',
5308 'grouping' : make_grouping([3, 3, 0]),
5309 'thousands_sep' : 'yyyyy'
5310 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005311
Stefan Krah1919b7e2012-03-21 18:25:23 +01005312 if CHAR_MAX == 127: # negative grouping in override
5313 self.assertRaises(ValueError, get_fmt, 12345,
5314 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005315
Stefan Krah1919b7e2012-03-21 18:25:23 +01005316 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5317 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005318
Stefan Krah0774e9b2012-04-05 15:21:58 +02005319 def test_exact_conversion(self):
5320 Decimal = C.Decimal
5321 localcontext = C.localcontext
5322 InvalidOperation = C.InvalidOperation
5323
5324 with localcontext() as c:
5325
5326 c.traps[InvalidOperation] = True
5327
5328 # Clamped
5329 x = "0e%d" % sys.maxsize
5330 self.assertRaises(InvalidOperation, Decimal, x)
5331
5332 x = "0e%d" % (-sys.maxsize-1)
5333 self.assertRaises(InvalidOperation, Decimal, x)
5334
5335 # Overflow
5336 x = "1e%d" % sys.maxsize
5337 self.assertRaises(InvalidOperation, Decimal, x)
5338
5339 # Underflow
5340 x = "1e%d" % (-sys.maxsize-1)
5341 self.assertRaises(InvalidOperation, Decimal, x)
5342
Stefan Krahff3eca02012-04-05 15:46:19 +02005343 def test_from_tuple(self):
5344 Decimal = C.Decimal
5345 localcontext = C.localcontext
5346 InvalidOperation = C.InvalidOperation
5347 Overflow = C.Overflow
5348 Underflow = C.Underflow
5349
5350 with localcontext() as c:
5351
5352 c.traps[InvalidOperation] = True
5353 c.traps[Overflow] = True
5354 c.traps[Underflow] = True
5355
5356 # SSIZE_MAX
5357 x = (1, (), sys.maxsize)
5358 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5359 self.assertRaises(InvalidOperation, Decimal, x)
5360
5361 x = (1, (0, 1, 2), sys.maxsize)
5362 self.assertRaises(Overflow, c.create_decimal, x)
5363 self.assertRaises(InvalidOperation, Decimal, x)
5364
5365 # SSIZE_MIN
5366 x = (1, (), -sys.maxsize-1)
5367 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5368 self.assertRaises(InvalidOperation, Decimal, x)
5369
5370 x = (1, (0, 1, 2), -sys.maxsize-1)
5371 self.assertRaises(Underflow, c.create_decimal, x)
5372 self.assertRaises(InvalidOperation, Decimal, x)
5373
5374 # OverflowError
5375 x = (1, (), sys.maxsize+1)
5376 self.assertRaises(OverflowError, c.create_decimal, x)
5377 self.assertRaises(OverflowError, Decimal, x)
5378
5379 x = (1, (), -sys.maxsize-2)
5380 self.assertRaises(OverflowError, c.create_decimal, x)
5381 self.assertRaises(OverflowError, Decimal, x)
5382
5383 # Specials
5384 x = (1, (), "N")
5385 self.assertEqual(str(Decimal(x)), '-sNaN')
5386 x = (1, (0,), "N")
5387 self.assertEqual(str(Decimal(x)), '-sNaN')
5388 x = (1, (0, 1), "N")
5389 self.assertEqual(str(Decimal(x)), '-sNaN1')
5390
Stefan Krah891ca9e2013-05-29 19:14:17 +02005391 def test_sizeof(self):
5392 Decimal = C.Decimal
5393 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5394
5395 self.assertGreater(Decimal(0).__sizeof__(), 0)
5396 if HAVE_CONFIG_64:
5397 x = Decimal(10**(19*24)).__sizeof__()
5398 y = Decimal(10**(19*25)).__sizeof__()
5399 self.assertEqual(y, x+8)
5400 else:
5401 x = Decimal(10**(9*24)).__sizeof__()
5402 y = Decimal(10**(9*25)).__sizeof__()
5403 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005404
Stefan Krah1919b7e2012-03-21 18:25:23 +01005405all_tests = [
5406 CExplicitConstructionTest, PyExplicitConstructionTest,
5407 CImplicitConstructionTest, PyImplicitConstructionTest,
5408 CFormatTest, PyFormatTest,
5409 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5410 CThreadingTest, PyThreadingTest,
5411 CUsabilityTest, PyUsabilityTest,
5412 CPythonAPItests, PyPythonAPItests,
5413 CContextAPItests, PyContextAPItests,
5414 CContextWithStatement, PyContextWithStatement,
5415 CContextFlags, PyContextFlags,
5416 CSpecialContexts, PySpecialContexts,
5417 CContextInputValidation, PyContextInputValidation,
5418 CContextSubclassing, PyContextSubclassing,
5419 CCoverage, PyCoverage,
5420 CFunctionality, PyFunctionality,
5421 CWhitebox, PyWhitebox,
5422 CIBMTestCases, PyIBMTestCases,
5423]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005424
Stefan Krah1919b7e2012-03-21 18:25:23 +01005425# Delete C tests if _decimal.so is not present.
5426if not C:
5427 all_tests = all_tests[1::2]
5428else:
5429 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005430
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005431
Zachary Ware66f29282014-06-02 16:01:29 -05005432def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005433 """ Execute the tests.
5434
Raymond Hettingered20ad82004-09-04 20:09:13 +00005435 Runs all arithmetic tests if arith is True or if the "decimal" resource
5436 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005437 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005438
Stefan Krah1919b7e2012-03-21 18:25:23 +01005439 init(C)
5440 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005441 global TEST_ALL, DEBUG
Zachary Ware66f29282014-06-02 16:01:29 -05005442 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005443 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005444
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005445 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005446 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005447 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005448 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005449
5450 # Dynamically build custom test definition for each file in the test
5451 # directory and add the definitions to the DecimalTest class. This
5452 # procedure insures that new files do not get skipped.
5453 for filename in os.listdir(directory):
5454 if '.decTest' not in filename or filename.startswith("."):
5455 continue
5456 head, tail = filename.split('.')
5457 if todo_tests is not None and head not in todo_tests:
5458 continue
5459 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005460 setattr(CIBMTestCases, 'test_' + head, tester)
5461 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005462 del filename, head, tail, tester
5463
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005464
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005465 try:
5466 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005467 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005468 from doctest import IGNORE_EXCEPTION_DETAIL
5469 savedecimal = sys.modules['decimal']
5470 if C:
5471 sys.modules['decimal'] = C
5472 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5473 sys.modules['decimal'] = P
5474 run_doctest(P, verbose)
5475 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005476 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005477 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5478 P.setcontext(ORIGINAL_CONTEXT[P])
5479 if not C:
5480 warnings.warn('C tests skipped: no module named _decimal.',
5481 UserWarning)
5482 if not orig_sys_decimal is sys.modules['decimal']:
5483 raise TestFailed("Internal error: unbalanced number of changes to "
5484 "sys.modules['decimal'].")
5485
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005486
5487if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005488 import optparse
5489 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5490 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5491 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5492 (opt, args) = p.parse_args()
5493
5494 if opt.skip:
5495 test_main(arith=False, verbose=True)
5496 elif args:
5497 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005498 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005499 test_main(arith=True, verbose=True)