blob: ea18c6393e80531a0bd828c1ed6fdb7b5920b093 [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,
38 run_with_locale)
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
81RoundingModes = {
82 C: (C.ROUND_UP, C.ROUND_DOWN, C.ROUND_CEILING, C.ROUND_FLOOR,
83 C.ROUND_HALF_UP, C.ROUND_HALF_DOWN, C.ROUND_HALF_EVEN,
84 C.ROUND_05UP) if C else None,
85 P: (P.ROUND_UP, P.ROUND_DOWN, P.ROUND_CEILING, P.ROUND_FLOOR,
86 P.ROUND_HALF_UP, P.ROUND_HALF_DOWN, P.ROUND_HALF_EVEN,
87 P.ROUND_05UP)
88}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000089
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000090# Tests are built around these assumed context defaults.
91# test_main() restores the original context.
Stefan Krah1919b7e2012-03-21 18:25:23 +010092ORIGINAL_CONTEXT = {
93 C: C.getcontext().copy() if C else None,
94 P: P.getcontext().copy()
95}
96def init(m):
97 if not m: return
98 DefaultTestContext = m.Context(
99 prec=9, rounding=m.ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
100 )
101 m.setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +0000102
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000103TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000104if __name__ == '__main__':
105 file = sys.argv[0]
106else:
107 file = __file__
108testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +0000109directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000110
Raymond Hettinger267b8682005-03-27 10:47:39 +0000111skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000112
113# Make sure it actually raises errors when not expected and caught in flags
114# Slower, since it runs some things several times.
115EXTENDEDERRORTEST = False
116
Stefan Krah1919b7e2012-03-21 18:25:23 +0100117# Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
118EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
119requires_extra_functionality = unittest.skipUnless(
120 EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
121skip_if_extra_functionality = unittest.skipIf(
122 EXTRA_FUNCTIONALITY, "test requires regular build")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000123
124
Stefan Krah1919b7e2012-03-21 18:25:23 +0100125class IBMTestCases(unittest.TestCase):
126 """Class which tests the Decimal class against the IBM test cases."""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000127
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000128 def setUp(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100129 self.context = self.decimal.Context()
130 self.readcontext = self.decimal.Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000131 self.ignore_list = ['#']
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000132
Stefan Krah1919b7e2012-03-21 18:25:23 +0100133 # List of individual .decTest test ids that correspond to tests that
134 # we're skipping for one reason or another.
135 self.skipped_test_ids = set([
136 # Skip implementation-specific scaleb tests.
137 'scbx164',
138 'scbx165',
139
140 # For some operations (currently exp, ln, log10, power), the decNumber
141 # reference implementation imposes additional restrictions on the context
142 # and operands. These restrictions are not part of the specification;
143 # however, the effect of these restrictions does show up in some of the
144 # testcases. We skip testcases that violate these restrictions, since
145 # Decimal behaves differently from decNumber for these testcases so these
146 # testcases would otherwise fail.
147 'expx901',
148 'expx902',
149 'expx903',
150 'expx905',
151 'lnx901',
152 'lnx902',
153 'lnx903',
154 'lnx905',
155 'logx901',
156 'logx902',
157 'logx903',
158 'logx905',
159 'powx1183',
160 'powx1184',
161 'powx4001',
162 'powx4002',
163 'powx4003',
164 'powx4005',
165 'powx4008',
166 'powx4010',
167 'powx4012',
168 'powx4014',
169 ])
170
171 if self.decimal == C:
172 # status has additional Subnormal, Underflow
173 self.skipped_test_ids.add('pwsx803')
174 self.skipped_test_ids.add('pwsx805')
175 # Correct rounding (skipped for decNumber, too)
176 self.skipped_test_ids.add('powx4302')
177 self.skipped_test_ids.add('powx4303')
178 self.skipped_test_ids.add('powx4342')
179 self.skipped_test_ids.add('powx4343')
180 # http://bugs.python.org/issue7049
181 self.skipped_test_ids.add('pwmx325')
182 self.skipped_test_ids.add('pwmx326')
183
184 # Map test directives to setter functions.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000185 self.ChangeDict = {'precision' : self.change_precision,
Stefan Krah1919b7e2012-03-21 18:25:23 +0100186 'rounding' : self.change_rounding_method,
187 'maxexponent' : self.change_max_exponent,
188 'minexponent' : self.change_min_exponent,
189 'clamp' : self.change_clamp}
190
191 # Name adapter to be able to change the Decimal and Context
192 # interface without changing the test files from Cowlishaw.
193 self.NameAdapter = {'and':'logical_and',
194 'apply':'_apply',
195 'class':'number_class',
196 'comparesig':'compare_signal',
197 'comparetotal':'compare_total',
198 'comparetotmag':'compare_total_mag',
199 'copy':'copy_decimal',
200 'copyabs':'copy_abs',
201 'copynegate':'copy_negate',
202 'copysign':'copy_sign',
203 'divideint':'divide_int',
204 'invert':'logical_invert',
205 'iscanonical':'is_canonical',
206 'isfinite':'is_finite',
207 'isinfinite':'is_infinite',
208 'isnan':'is_nan',
209 'isnormal':'is_normal',
210 'isqnan':'is_qnan',
211 'issigned':'is_signed',
212 'issnan':'is_snan',
213 'issubnormal':'is_subnormal',
214 'iszero':'is_zero',
215 'maxmag':'max_mag',
216 'minmag':'min_mag',
217 'nextminus':'next_minus',
218 'nextplus':'next_plus',
219 'nexttoward':'next_toward',
220 'or':'logical_or',
221 'reduce':'normalize',
222 'remaindernear':'remainder_near',
223 'samequantum':'same_quantum',
224 'squareroot':'sqrt',
225 'toeng':'to_eng_string',
226 'tointegral':'to_integral_value',
227 'tointegralx':'to_integral_exact',
228 'tosci':'to_sci_string',
229 'xor':'logical_xor'}
230
231 # Map test-case names to roundings.
232 self.RoundingDict = {'ceiling' : self.decimal.ROUND_CEILING,
233 'down' : self.decimal.ROUND_DOWN,
234 'floor' : self.decimal.ROUND_FLOOR,
235 'half_down' : self.decimal.ROUND_HALF_DOWN,
236 'half_even' : self.decimal.ROUND_HALF_EVEN,
237 'half_up' : self.decimal.ROUND_HALF_UP,
238 'up' : self.decimal.ROUND_UP,
239 '05up' : self.decimal.ROUND_05UP}
240
241 # Map the test cases' error names to the actual errors.
242 self.ErrorNames = {'clamped' : self.decimal.Clamped,
243 'conversion_syntax' : self.decimal.InvalidOperation,
244 'division_by_zero' : self.decimal.DivisionByZero,
245 'division_impossible' : self.decimal.InvalidOperation,
246 'division_undefined' : self.decimal.InvalidOperation,
247 'inexact' : self.decimal.Inexact,
248 'invalid_context' : self.decimal.InvalidOperation,
249 'invalid_operation' : self.decimal.InvalidOperation,
250 'overflow' : self.decimal.Overflow,
251 'rounded' : self.decimal.Rounded,
252 'subnormal' : self.decimal.Subnormal,
253 'underflow' : self.decimal.Underflow}
254
255 # The following functions return True/False rather than a
256 # Decimal instance.
257 self.LogicalFunctions = ('is_canonical',
258 'is_finite',
259 'is_infinite',
260 'is_nan',
261 'is_normal',
262 'is_qnan',
263 'is_signed',
264 'is_snan',
265 'is_subnormal',
266 'is_zero',
267 'same_quantum')
268
269 def read_unlimited(self, v, context):
270 """Work around the limitations of the 32-bit _decimal version. The
271 guaranteed maximum values for prec, Emax etc. are 425000000,
272 but higher values usually work, except for rare corner cases.
273 In particular, all of the IBM tests pass with maximum values
274 of 1070000000."""
275 if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
276 self.readcontext._unsafe_setprec(1070000000)
277 self.readcontext._unsafe_setemax(1070000000)
278 self.readcontext._unsafe_setemin(-1070000000)
279 return self.readcontext.create_decimal(v)
280 else:
281 return self.decimal.Decimal(v, context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000282
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000283 def eval_file(self, file):
284 global skip_expected
285 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000286 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000287 return
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000288 with open(file) as f:
289 for line in f:
290 line = line.replace('\r\n', '').replace('\n', '')
291 #print line
292 try:
293 t = self.eval_line(line)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100294 except self.decimal.DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200295 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000296 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000297
298 return
299
300 def eval_line(self, s):
301 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
302 s = (s.split('->')[0] + '->' +
303 s.split('->')[1].split('--')[0]).strip()
304 else:
305 s = s.split('--')[0].strip()
306
307 for ignore in self.ignore_list:
308 if s.find(ignore) >= 0:
309 #print s.split()[0], 'NotImplemented--', ignore
310 return
311 if not s:
312 return
313 elif ':' in s:
314 return self.eval_directive(s)
315 else:
316 return self.eval_equation(s)
317
318 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000319 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000320 if funct == 'rounding':
Stefan Krah1919b7e2012-03-21 18:25:23 +0100321 value = self.RoundingDict[value]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000322 else:
323 try:
324 value = int(value)
325 except ValueError:
326 pass
327
Stefan Krah1919b7e2012-03-21 18:25:23 +0100328 funct = self.ChangeDict.get(funct, (lambda *args: None))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000329 funct(value)
330
331 def eval_equation(self, s):
Raymond Hettingered20ad82004-09-04 20:09:13 +0000332
333 if not TEST_ALL and random.random() < 0.90:
334 return
335
Stefan Krah1919b7e2012-03-21 18:25:23 +0100336 self.context.clear_flags()
337
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000338 try:
339 Sides = s.split('->')
340 L = Sides[0].strip().split()
341 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000342 if DEBUG:
343 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000344 funct = L[1].lower()
345 valstemp = L[2:]
346 L = Sides[1].strip().split()
347 ans = L[0]
348 exceptions = L[1:]
349 except (TypeError, AttributeError, IndexError):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100350 raise self.decimal.InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000351 def FixQuotes(val):
352 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
353 val = val.replace("'", '').replace('"', '')
354 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
355 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000356
Stefan Krah1919b7e2012-03-21 18:25:23 +0100357 if id in self.skipped_test_ids:
Mark Dickinson8a546532009-10-08 16:30:38 +0000358 return
359
Stefan Krah1919b7e2012-03-21 18:25:23 +0100360 fname = self.NameAdapter.get(funct, funct)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000361 if fname == 'rescale':
362 return
363 funct = getattr(self.context, fname)
364 vals = []
365 conglomerate = ''
366 quote = 0
Stefan Krah1919b7e2012-03-21 18:25:23 +0100367 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000368
Stefan Krah1919b7e2012-03-21 18:25:23 +0100369 for exception in Signals[self.decimal]:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000370 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000371 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000372 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000373 for i, val in enumerate(valstemp):
374 if val.count("'") % 2 == 1:
375 quote = 1 - quote
376 if quote:
377 conglomerate = conglomerate + ' ' + val
378 continue
379 else:
380 val = conglomerate + val
381 conglomerate = ''
382 v = FixQuotes(val)
383 if fname in ('to_sci_string', 'to_eng_string'):
384 if EXTENDEDERRORTEST:
385 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000386 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000387 try:
388 funct(self.context.create_decimal(v))
389 except error:
390 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100391 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000392 self.fail("Raised %s in %s when %s disabled" % \
393 (e, s, error))
394 else:
395 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000396 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000397 v = self.context.create_decimal(v)
398 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +0100399 v = self.read_unlimited(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000400 vals.append(v)
401
402 ans = FixQuotes(ans)
403
404 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
405 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000406 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000407 try:
408 funct(*vals)
409 except error:
410 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100411 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000412 self.fail("Raised %s in %s when %s disabled" % \
413 (e, s, error))
414 else:
415 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000416 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000417
418 # as above, but add traps cumulatively, to check precedence
Stefan Krah1919b7e2012-03-21 18:25:23 +0100419 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions]
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000420 for error in ordered_errors:
421 self.context.traps[error] = 1
422 try:
423 funct(*vals)
424 except error:
425 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100426 except Signals[self.decimal] as e:
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000427 self.fail("Raised %s in %s; expected %s" %
428 (type(e), s, error))
429 else:
430 self.fail("Did not raise %s in %s" % (error, s))
431 # reset traps
432 for error in ordered_errors:
433 self.context.traps[error] = 0
434
435
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000436 if DEBUG:
437 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000438 try:
439 result = str(funct(*vals))
Stefan Krah1919b7e2012-03-21 18:25:23 +0100440 if fname in self.LogicalFunctions:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000441 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Stefan Krah1919b7e2012-03-21 18:25:23 +0100442 except Signals[self.decimal] as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000443 self.fail("Raised %s in %s" % (error, s))
444 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000445 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000446 raise
447
448 myexceptions = self.getexceptions()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000449
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000450 myexceptions.sort(key=repr)
451 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000452
453 self.assertEqual(result, ans,
454 'Incorrect answer for ' + s + ' -- got ' + result)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100455
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000456 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000457 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000458 return
459
460 def getexceptions(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100461 return [e for e in Signals[self.decimal] if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000462
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000463 def change_precision(self, prec):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100464 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
465 self.context._unsafe_setprec(prec)
466 else:
467 self.context.prec = prec
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000468 def change_rounding_method(self, rounding):
469 self.context.rounding = rounding
470 def change_min_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100471 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
472 self.context._unsafe_setemin(exp)
473 else:
474 self.context.Emin = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000475 def change_max_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100476 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
477 self.context._unsafe_setemax(exp)
478 else:
479 self.context.Emax = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000480 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000481 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000482
Stefan Krah1919b7e2012-03-21 18:25:23 +0100483class CIBMTestCases(IBMTestCases):
484 decimal = C
485class PyIBMTestCases(IBMTestCases):
486 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000487
488# The following classes test the behaviour of Decimal according to PEP 327
489
Stefan Krah1919b7e2012-03-21 18:25:23 +0100490class ExplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000491 '''Unit tests for Explicit Construction cases of Decimal.'''
492
493 def test_explicit_empty(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100494 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000495 self.assertEqual(Decimal(), Decimal("0"))
496
497 def test_explicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100498 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000499 self.assertRaises(TypeError, Decimal, None)
500
501 def test_explicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100502 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000503
504 #positive
505 d = Decimal(45)
506 self.assertEqual(str(d), '45')
507
508 #very large positive
509 d = Decimal(500000123)
510 self.assertEqual(str(d), '500000123')
511
512 #negative
513 d = Decimal(-45)
514 self.assertEqual(str(d), '-45')
515
516 #zero
517 d = Decimal(0)
518 self.assertEqual(str(d), '0')
519
Stefan Krah1919b7e2012-03-21 18:25:23 +0100520 # single word longs
521 for n in range(0, 32):
522 for sign in (-1, 1):
523 for x in range(-5, 5):
524 i = sign * (2**n + x)
525 d = Decimal(i)
526 self.assertEqual(str(d), str(i))
527
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000528 def test_explicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100529 Decimal = self.decimal.Decimal
530 InvalidOperation = self.decimal.InvalidOperation
531 localcontext = self.decimal.localcontext
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000532
533 #empty
534 self.assertEqual(str(Decimal('')), 'NaN')
535
536 #int
537 self.assertEqual(str(Decimal('45')), '45')
538
539 #float
540 self.assertEqual(str(Decimal('45.34')), '45.34')
541
542 #engineer notation
543 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
544
545 #just not a number
546 self.assertEqual(str(Decimal('ugly')), 'NaN')
547
Christian Heimesa62da1d2008-01-12 19:39:10 +0000548 #leading and trailing whitespace permitted
549 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
550 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
Stefan Krah1919b7e2012-03-21 18:25:23 +0100551 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
552
553 # unicode whitespace
554 for lead in ["", ' ', '\u00a0', '\u205f']:
555 for trail in ["", ' ', '\u00a0', '\u205f']:
556 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
557 '9.311E+28')
558
559 with localcontext() as c:
560 c.traps[InvalidOperation] = True
561 # Invalid string
562 self.assertRaises(InvalidOperation, Decimal, "xyz")
563 # Two arguments max
564 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
565
566 # space within the numeric part
567 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
568 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
569
570 # unicode whitespace
571 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
572 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
573
574 # embedded NUL
575 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
576
Christian Heimesa62da1d2008-01-12 19:39:10 +0000577
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000578 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100579 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000580
581 #zero
582 d = Decimal( (0, (0,), 0) )
583 self.assertEqual(str(d), '0')
584
585 #int
586 d = Decimal( (1, (4, 5), 0) )
587 self.assertEqual(str(d), '-45')
588
589 #float
590 d = Decimal( (0, (4, 5, 3, 4), -2) )
591 self.assertEqual(str(d), '45.34')
592
593 #weird
594 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
595 self.assertEqual(str(d), '-4.34913534E-17')
596
Stefan Krah1919b7e2012-03-21 18:25:23 +0100597 #inf
598 d = Decimal( (0, (), "F") )
599 self.assertEqual(str(d), 'Infinity')
600
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000601 #wrong number of items
602 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
603
604 #bad sign
605 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000606 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
607 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000608
609 #bad exp
610 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000611 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
612 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000613
614 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100615 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000616 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
617 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000618 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000619 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000620
Stefan Krah1919b7e2012-03-21 18:25:23 +0100621 def test_explicit_from_list(self):
622 Decimal = self.decimal.Decimal
623
624 d = Decimal([0, [0], 0])
625 self.assertEqual(str(d), '0')
626
627 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
628 self.assertEqual(str(d), '-4.34913534E-17')
629
630 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
631 self.assertEqual(str(d), '-4.34913534E-17')
632
633 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
634 self.assertEqual(str(d), '-4.34913534E-17')
635
Antoine Pitrou503ab332010-03-30 18:56:19 +0000636 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100637 Decimal = self.decimal.Decimal
638
Antoine Pitrou503ab332010-03-30 18:56:19 +0000639 self.assertIs(bool(Decimal(0)), False)
640 self.assertIs(bool(Decimal(1)), True)
641 self.assertEqual(Decimal(False), Decimal(0))
642 self.assertEqual(Decimal(True), Decimal(1))
643
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000644 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100645 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000646
647 #positive
648 d = Decimal(45)
649 e = Decimal(d)
650 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000651
652 #very large positive
653 d = Decimal(500000123)
654 e = Decimal(d)
655 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000656
657 #negative
658 d = Decimal(-45)
659 e = Decimal(d)
660 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000661
662 #zero
663 d = Decimal(0)
664 e = Decimal(d)
665 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000666
Raymond Hettinger96798592010-04-02 16:58:27 +0000667 @requires_IEEE_754
668 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100669
670 Decimal = self.decimal.Decimal
671
Raymond Hettinger96798592010-04-02 16:58:27 +0000672 r = Decimal(0.1)
673 self.assertEqual(type(r), Decimal)
674 self.assertEqual(str(r),
675 '0.1000000000000000055511151231257827021181583404541015625')
676 self.assertTrue(Decimal(float('nan')).is_qnan())
677 self.assertTrue(Decimal(float('inf')).is_infinite())
678 self.assertTrue(Decimal(float('-inf')).is_infinite())
679 self.assertEqual(str(Decimal(float('nan'))),
680 str(Decimal('NaN')))
681 self.assertEqual(str(Decimal(float('inf'))),
682 str(Decimal('Infinity')))
683 self.assertEqual(str(Decimal(float('-inf'))),
684 str(Decimal('-Infinity')))
685 self.assertEqual(str(Decimal(float('-0.0'))),
686 str(Decimal('-0')))
687 for i in range(200):
688 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
689 self.assertEqual(x, float(Decimal(x))) # roundtrip
690
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000691 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100692 Decimal = self.decimal.Decimal
693 InvalidOperation = self.decimal.InvalidOperation
694 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000695
Stefan Krah1919b7e2012-03-21 18:25:23 +0100696 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000697 nc.prec = 3
698
699 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000700 d = Decimal()
701 self.assertEqual(str(d), '0')
702 d = nc.create_decimal()
703 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000704
705 # from None
706 self.assertRaises(TypeError, nc.create_decimal, None)
707
708 # from int
709 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000710 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000711 self.assertEqual(nc.create_decimal(45678),
712 nc.create_decimal('457E+2'))
713
714 # from string
715 d = Decimal('456789')
716 self.assertEqual(str(d), '456789')
717 d = nc.create_decimal('456789')
718 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000719 # leading and trailing whitespace should result in a NaN;
720 # spaces are already checked in Cowlishaw's test-suite, so
721 # here we just check that a trailing newline results in a NaN
722 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000723
724 # from tuples
725 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
726 self.assertEqual(str(d), '-4.34913534E-17')
727 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
728 self.assertEqual(str(d), '-4.35E-17')
729
730 # from Decimal
731 prevdec = Decimal(500000123)
732 d = Decimal(prevdec)
733 self.assertEqual(str(d), '500000123')
734 d = nc.create_decimal(prevdec)
735 self.assertEqual(str(d), '5.00E+8')
736
Stefan Krah1919b7e2012-03-21 18:25:23 +0100737 # more integers
738 nc.prec = 28
739 nc.traps[InvalidOperation] = True
740
741 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
742 2**31-1, 2**31, 2**63-1, 2**63]:
743 d = nc.create_decimal(v)
744 self.assertTrue(isinstance(d, Decimal))
745 self.assertEqual(int(d), v)
746
747 nc.prec = 3
748 nc.traps[Rounded] = True
749 self.assertRaises(Rounded, nc.create_decimal, 1234)
750
751 # from string
752 nc.prec = 28
753 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
754 self.assertEqual(str(nc.create_decimal('45')), '45')
755 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
756 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
757
758 # invalid arguments
759 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
760 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
761 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
762
763 # too many NaN payload digits
764 nc.prec = 3
765 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
766 self.assertRaises(InvalidOperation, nc.create_decimal,
767 Decimal('NaN12345'))
768
769 nc.traps[InvalidOperation] = False
770 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
771 self.assertTrue(nc.flags[InvalidOperation])
772
773 nc.flags[InvalidOperation] = False
774 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
775 self.assertTrue(nc.flags[InvalidOperation])
776
777 def test_explicit_context_create_from_float(self):
778
779 Decimal = self.decimal.Decimal
780
781 nc = self.decimal.Context()
782 r = nc.create_decimal(0.1)
783 self.assertEqual(type(r), Decimal)
784 self.assertEqual(str(r), '0.1000000000000000055511151231')
785 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
786 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
787 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
788 self.assertEqual(str(nc.create_decimal(float('nan'))),
789 str(nc.create_decimal('NaN')))
790 self.assertEqual(str(nc.create_decimal(float('inf'))),
791 str(nc.create_decimal('Infinity')))
792 self.assertEqual(str(nc.create_decimal(float('-inf'))),
793 str(nc.create_decimal('-Infinity')))
794 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
795 str(nc.create_decimal('-0')))
796 nc.prec = 100
797 for i in range(200):
798 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
799 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
800
Mark Dickinson345adc42009-08-02 10:14:23 +0000801 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100802 Decimal = self.decimal.Decimal
803
Mark Dickinson345adc42009-08-02 10:14:23 +0000804 test_values = {
805 '\uff11': '1',
806 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
807 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
808 }
809 for input, expected in test_values.items():
810 self.assertEqual(str(Decimal(input)), expected)
811
Stefan Krah1919b7e2012-03-21 18:25:23 +0100812class CExplicitConstructionTest(ExplicitConstructionTest):
813 decimal = C
814class PyExplicitConstructionTest(ExplicitConstructionTest):
815 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000816
Stefan Krah1919b7e2012-03-21 18:25:23 +0100817class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000818 '''Unit tests for Implicit Construction cases of Decimal.'''
819
820 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100821 Decimal = self.decimal.Decimal
822 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000823
824 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100825 Decimal = self.decimal.Decimal
826
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000827 #normal
828 self.assertEqual(str(Decimal(5) + 45), '50')
829 #exceeding precision
830 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
831
832 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100833 Decimal = self.decimal.Decimal
834 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000835
836 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100837 Decimal = self.decimal.Decimal
838 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000839
840 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100841 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000842 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
843
Raymond Hettinger267b8682005-03-27 10:47:39 +0000844 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100845 Decimal = self.decimal.Decimal
846
Raymond Hettinger267b8682005-03-27 10:47:39 +0000847 # Allow other classes to be trained to interact with Decimals
848 class E:
849 def __divmod__(self, other):
850 return 'divmod ' + str(other)
851 def __rdivmod__(self, other):
852 return str(other) + ' rdivmod'
853 def __lt__(self, other):
854 return 'lt ' + str(other)
855 def __gt__(self, other):
856 return 'gt ' + str(other)
857 def __le__(self, other):
858 return 'le ' + str(other)
859 def __ge__(self, other):
860 return 'ge ' + str(other)
861 def __eq__(self, other):
862 return 'eq ' + str(other)
863 def __ne__(self, other):
864 return 'ne ' + str(other)
865
866 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
867 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
868 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
869 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
870 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
871 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
872 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
873 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
874
875 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000876 oplist = [
877 ('+', '__add__', '__radd__'),
878 ('-', '__sub__', '__rsub__'),
879 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000880 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000881 ('%', '__mod__', '__rmod__'),
882 ('//', '__floordiv__', '__rfloordiv__'),
883 ('**', '__pow__', '__rpow__')
884 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000885
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000886 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000887 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
888 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
889 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
890 'str' + lop + '10')
891 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
892 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000893
Stefan Krah1919b7e2012-03-21 18:25:23 +0100894class CImplicitConstructionTest(ImplicitConstructionTest):
895 decimal = C
896class PyImplicitConstructionTest(ImplicitConstructionTest):
897 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000898
Stefan Krah1919b7e2012-03-21 18:25:23 +0100899class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000900 '''Unit tests for the format function.'''
901 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100902 Decimal = self.decimal.Decimal
903
Christian Heimesf16baeb2008-02-29 14:57:44 +0000904 # triples giving a format, a Decimal, and the expected result
905 test_values = [
906 ('e', '0E-15', '0e-15'),
907 ('e', '2.3E-15', '2.3e-15'),
908 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
909 ('e', '2.30000E-15', '2.30000e-15'),
910 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
911 ('e', '1.5', '1.5e+0'),
912 ('e', '0.15', '1.5e-1'),
913 ('e', '0.015', '1.5e-2'),
914 ('e', '0.0000000000015', '1.5e-12'),
915 ('e', '15.0', '1.50e+1'),
916 ('e', '-15', '-1.5e+1'),
917 ('e', '0', '0e+0'),
918 ('e', '0E1', '0e+1'),
919 ('e', '0.0', '0e-1'),
920 ('e', '0.00', '0e-2'),
921 ('.6e', '0E-15', '0.000000e-9'),
922 ('.6e', '0', '0.000000e+6'),
923 ('.6e', '9.999999', '9.999999e+0'),
924 ('.6e', '9.9999999', '1.000000e+1'),
925 ('.6e', '-1.23e5', '-1.230000e+5'),
926 ('.6e', '1.23456789e-3', '1.234568e-3'),
927 ('f', '0', '0'),
928 ('f', '0.0', '0.0'),
929 ('f', '0E-2', '0.00'),
930 ('f', '0.00E-8', '0.0000000000'),
931 ('f', '0E1', '0'), # loses exponent information
932 ('f', '3.2E1', '32'),
933 ('f', '3.2E2', '320'),
934 ('f', '3.20E2', '320'),
935 ('f', '3.200E2', '320.0'),
936 ('f', '3.2E-6', '0.0000032'),
937 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
938 ('.6f', '0E1', '0.000000'),
939 ('.6f', '0', '0.000000'),
940 ('.0f', '0', '0'), # no decimal point
941 ('.0f', '0e-2', '0'),
942 ('.0f', '3.14159265', '3'),
943 ('.1f', '3.14159265', '3.1'),
944 ('.4f', '3.14159265', '3.1416'),
945 ('.6f', '3.14159265', '3.141593'),
946 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
947 ('.8f', '3.14159265', '3.14159265'),
948 ('.9f', '3.14159265', '3.141592650'),
949
950 ('g', '0', '0'),
951 ('g', '0.0', '0.0'),
952 ('g', '0E1', '0e+1'),
953 ('G', '0E1', '0E+1'),
954 ('g', '0E-5', '0.00000'),
955 ('g', '0E-6', '0.000000'),
956 ('g', '0E-7', '0e-7'),
957 ('g', '-0E2', '-0e+2'),
958 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100959 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000960 ('.1g', '3.14159265', '3'),
961 ('.2g', '3.14159265', '3.1'),
962 ('.5g', '3.14159265', '3.1416'),
963 ('.7g', '3.14159265', '3.141593'),
964 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
965 ('.9g', '3.14159265', '3.14159265'),
966 ('.10g', '3.14159265', '3.14159265'), # don't pad
967
968 ('%', '0E1', '0%'),
969 ('%', '0E0', '0%'),
970 ('%', '0E-1', '0%'),
971 ('%', '0E-2', '0%'),
972 ('%', '0E-3', '0.0%'),
973 ('%', '0E-4', '0.00%'),
974
975 ('.3%', '0', '0.000%'), # all zeros treated equally
976 ('.3%', '0E10', '0.000%'),
977 ('.3%', '0E-10', '0.000%'),
978 ('.3%', '2.34', '234.000%'),
979 ('.3%', '1.234567', '123.457%'),
980 ('.0%', '1.23', '123%'),
981
982 ('e', 'NaN', 'NaN'),
983 ('f', '-NaN123', '-NaN123'),
984 ('+g', 'NaN456', '+NaN456'),
985 ('.3e', 'Inf', 'Infinity'),
986 ('.16f', '-Inf', '-Infinity'),
987 ('.0g', '-sNaN', '-sNaN'),
988
989 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000990
Mark Dickinson79f52032009-03-17 23:12:51 +0000991 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000992 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000993 ('<6', '123', '123 '),
994 ('>6', '123', ' 123'),
995 ('^6', '123', ' 123 '),
996 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000997 ('#<10', 'NaN', 'NaN#######'),
998 ('#<10', '-4.3', '-4.3######'),
999 ('#<+10', '0.0130', '+0.0130###'),
1000 ('#< 10', '0.0130', ' 0.0130###'),
1001 ('@>10', '-Inf', '@-Infinity'),
1002 ('#>5', '-Inf', '-Infinity'),
1003 ('?^5', '123', '?123?'),
1004 ('%^6', '123', '%123%%'),
1005 (' ^6', '-45.6', '-45.6 '),
1006 ('/=10', '-45.6', '-/////45.6'),
1007 ('/=+10', '45.6', '+/////45.6'),
1008 ('/= 10', '45.6', ' /////45.6'),
1009
1010 # thousands separator
1011 (',', '1234567', '1,234,567'),
1012 (',', '123456', '123,456'),
1013 (',', '12345', '12,345'),
1014 (',', '1234', '1,234'),
1015 (',', '123', '123'),
1016 (',', '12', '12'),
1017 (',', '1', '1'),
1018 (',', '0', '0'),
1019 (',', '-1234567', '-1,234,567'),
1020 (',', '-123456', '-123,456'),
1021 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001022 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001023 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1024 ('+08,', '123456', '+123,456'), # but not if there's a sign
1025 (' 08,', '123456', ' 123,456'),
1026 ('08,', '-123456', '-123,456'),
1027 ('+09,', '123456', '+0,123,456'),
1028 # ... with fractional part...
1029 ('07,', '1234.56', '1,234.56'),
1030 ('08,', '1234.56', '1,234.56'),
1031 ('09,', '1234.56', '01,234.56'),
1032 ('010,', '1234.56', '001,234.56'),
1033 ('011,', '1234.56', '0,001,234.56'),
1034 ('012,', '1234.56', '0,001,234.56'),
1035 ('08,.1f', '1234.5', '01,234.5'),
1036 # no thousands separators in fraction part
1037 (',', '1.23456789', '1.23456789'),
1038 (',%', '123.456789', '12,345.6789%'),
1039 (',e', '123456', '1.23456e+5'),
1040 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001041
1042 # issue 6850
1043 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001044 ]
1045 for fmt, d, result in test_values:
1046 self.assertEqual(format(Decimal(d), fmt), result)
1047
Stefan Krah1919b7e2012-03-21 18:25:23 +01001048 # bytes format argument
1049 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1050
Mark Dickinson79f52032009-03-17 23:12:51 +00001051 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001052 Decimal = self.decimal.Decimal
1053
Mark Dickinson79f52032009-03-17 23:12:51 +00001054 try:
1055 from locale import CHAR_MAX
1056 except ImportError:
1057 return
1058
Stefan Krah1919b7e2012-03-21 18:25:23 +01001059 def make_grouping(lst):
1060 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1061
1062 def get_fmt(x, override=None, fmt='n'):
1063 if self.decimal == C:
1064 return Decimal(x).__format__(fmt, override)
1065 else:
1066 return Decimal(x).__format__(fmt, _localeconv=override)
1067
Mark Dickinson79f52032009-03-17 23:12:51 +00001068 # Set up some localeconv-like dictionaries
1069 en_US = {
1070 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001071 'grouping' : make_grouping([3, 3, 0]),
1072 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001073 }
1074
1075 fr_FR = {
1076 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001077 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001078 'thousands_sep' : ''
1079 }
1080
1081 ru_RU = {
1082 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001083 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001084 'thousands_sep' : ' '
1085 }
1086
1087 crazy = {
1088 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001089 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001090 'thousands_sep' : '-'
1091 }
1092
Stefan Krah1919b7e2012-03-21 18:25:23 +01001093 dotsep_wide = {
1094 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1095 'grouping': make_grouping([3, 3, 0]),
1096 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1097 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001098
1099 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1100 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1101 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1102 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1103
1104 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1105 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1106 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1107 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1108
1109 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1110 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1111 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1112 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1113
Mark Dickinson7303b592009-03-18 08:25:36 +00001114 # zero padding
1115 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1116 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1117 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1118 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1119
1120 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1121 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1122 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1123 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1124 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1125 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1126
1127 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1128 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1129 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1130 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1131 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1132 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1133 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1134 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1135
Stefan Krah1919b7e2012-03-21 18:25:23 +01001136 # wide char separator and decimal point
1137 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1138 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001139
Stefan Krah6fb204a2012-09-28 16:18:54 +02001140 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001141 def test_wide_char_separator_decimal_point(self):
1142 # locale with wide char separator and decimal point
Stefan Krah8a491a82012-09-28 17:17:11 +02001143 import locale
Stefan Krah1919b7e2012-03-21 18:25:23 +01001144 Decimal = self.decimal.Decimal
1145
Stefan Krah8a491a82012-09-28 17:17:11 +02001146 decimal_point = locale.localeconv()['decimal_point']
1147 thousands_sep = locale.localeconv()['thousands_sep']
1148 if decimal_point != '\u066b' or thousands_sep != '\u066c':
1149 return
1150
Stefan Krah1919b7e2012-03-21 18:25:23 +01001151 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1152 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001153
1154class CFormatTest(FormatTest):
1155 decimal = C
1156class PyFormatTest(FormatTest):
1157 decimal = P
1158
1159class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001160 '''Unit tests for all arithmetic operators, binary and unary.'''
1161
1162 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001163 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001164
1165 d1 = Decimal('-11.1')
1166 d2 = Decimal('22.2')
1167
1168 #two Decimals
1169 self.assertEqual(d1+d2, Decimal('11.1'))
1170 self.assertEqual(d2+d1, Decimal('11.1'))
1171
1172 #with other type, left
1173 c = d1 + 5
1174 self.assertEqual(c, Decimal('-6.1'))
1175 self.assertEqual(type(c), type(d1))
1176
1177 #with other type, right
1178 c = 5 + d1
1179 self.assertEqual(c, Decimal('-6.1'))
1180 self.assertEqual(type(c), type(d1))
1181
1182 #inline with decimal
1183 d1 += d2
1184 self.assertEqual(d1, Decimal('11.1'))
1185
1186 #inline with other type
1187 d1 += 5
1188 self.assertEqual(d1, Decimal('16.1'))
1189
1190 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001191 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001192
1193 d1 = Decimal('-11.1')
1194 d2 = Decimal('22.2')
1195
1196 #two Decimals
1197 self.assertEqual(d1-d2, Decimal('-33.3'))
1198 self.assertEqual(d2-d1, Decimal('33.3'))
1199
1200 #with other type, left
1201 c = d1 - 5
1202 self.assertEqual(c, Decimal('-16.1'))
1203 self.assertEqual(type(c), type(d1))
1204
1205 #with other type, right
1206 c = 5 - d1
1207 self.assertEqual(c, Decimal('16.1'))
1208 self.assertEqual(type(c), type(d1))
1209
1210 #inline with decimal
1211 d1 -= d2
1212 self.assertEqual(d1, Decimal('-33.3'))
1213
1214 #inline with other type
1215 d1 -= 5
1216 self.assertEqual(d1, Decimal('-38.3'))
1217
1218 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001219 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001220
1221 d1 = Decimal('-5')
1222 d2 = Decimal('3')
1223
1224 #two Decimals
1225 self.assertEqual(d1*d2, Decimal('-15'))
1226 self.assertEqual(d2*d1, Decimal('-15'))
1227
1228 #with other type, left
1229 c = d1 * 5
1230 self.assertEqual(c, Decimal('-25'))
1231 self.assertEqual(type(c), type(d1))
1232
1233 #with other type, right
1234 c = 5 * d1
1235 self.assertEqual(c, Decimal('-25'))
1236 self.assertEqual(type(c), type(d1))
1237
1238 #inline with decimal
1239 d1 *= d2
1240 self.assertEqual(d1, Decimal('-15'))
1241
1242 #inline with other type
1243 d1 *= 5
1244 self.assertEqual(d1, Decimal('-75'))
1245
1246 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001247 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001248
1249 d1 = Decimal('-5')
1250 d2 = Decimal('2')
1251
1252 #two Decimals
1253 self.assertEqual(d1/d2, Decimal('-2.5'))
1254 self.assertEqual(d2/d1, Decimal('-0.4'))
1255
1256 #with other type, left
1257 c = d1 / 4
1258 self.assertEqual(c, Decimal('-1.25'))
1259 self.assertEqual(type(c), type(d1))
1260
1261 #with other type, right
1262 c = 4 / d1
1263 self.assertEqual(c, Decimal('-0.8'))
1264 self.assertEqual(type(c), type(d1))
1265
1266 #inline with decimal
1267 d1 /= d2
1268 self.assertEqual(d1, Decimal('-2.5'))
1269
1270 #inline with other type
1271 d1 /= 4
1272 self.assertEqual(d1, Decimal('-0.625'))
1273
1274 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001275 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001276
1277 d1 = Decimal('5')
1278 d2 = Decimal('2')
1279
1280 #two Decimals
1281 self.assertEqual(d1//d2, Decimal('2'))
1282 self.assertEqual(d2//d1, Decimal('0'))
1283
1284 #with other type, left
1285 c = d1 // 4
1286 self.assertEqual(c, Decimal('1'))
1287 self.assertEqual(type(c), type(d1))
1288
1289 #with other type, right
1290 c = 7 // d1
1291 self.assertEqual(c, Decimal('1'))
1292 self.assertEqual(type(c), type(d1))
1293
1294 #inline with decimal
1295 d1 //= d2
1296 self.assertEqual(d1, Decimal('2'))
1297
1298 #inline with other type
1299 d1 //= 2
1300 self.assertEqual(d1, Decimal('1'))
1301
1302 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001303 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001304
1305 d1 = Decimal('5')
1306 d2 = Decimal('2')
1307
1308 #two Decimals
1309 self.assertEqual(d1**d2, Decimal('25'))
1310 self.assertEqual(d2**d1, Decimal('32'))
1311
1312 #with other type, left
1313 c = d1 ** 4
1314 self.assertEqual(c, Decimal('625'))
1315 self.assertEqual(type(c), type(d1))
1316
1317 #with other type, right
1318 c = 7 ** d1
1319 self.assertEqual(c, Decimal('16807'))
1320 self.assertEqual(type(c), type(d1))
1321
1322 #inline with decimal
1323 d1 **= d2
1324 self.assertEqual(d1, Decimal('25'))
1325
1326 #inline with other type
1327 d1 **= 4
1328 self.assertEqual(d1, Decimal('390625'))
1329
1330 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001331 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001332
1333 d1 = Decimal('5')
1334 d2 = Decimal('2')
1335
1336 #two Decimals
1337 self.assertEqual(d1%d2, Decimal('1'))
1338 self.assertEqual(d2%d1, Decimal('2'))
1339
1340 #with other type, left
1341 c = d1 % 4
1342 self.assertEqual(c, Decimal('1'))
1343 self.assertEqual(type(c), type(d1))
1344
1345 #with other type, right
1346 c = 7 % d1
1347 self.assertEqual(c, Decimal('2'))
1348 self.assertEqual(type(c), type(d1))
1349
1350 #inline with decimal
1351 d1 %= d2
1352 self.assertEqual(d1, Decimal('1'))
1353
1354 #inline with other type
1355 d1 %= 4
1356 self.assertEqual(d1, Decimal('1'))
1357
1358 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001359 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001360
1361 d1 = Decimal('5')
1362 d2 = Decimal('2')
1363
1364 #two Decimals
1365 (p, q) = divmod(d1, d2)
1366 self.assertEqual(p, Decimal('2'))
1367 self.assertEqual(q, Decimal('1'))
1368 self.assertEqual(type(p), type(d1))
1369 self.assertEqual(type(q), type(d1))
1370
1371 #with other type, left
1372 (p, q) = divmod(d1, 4)
1373 self.assertEqual(p, Decimal('1'))
1374 self.assertEqual(q, Decimal('1'))
1375 self.assertEqual(type(p), type(d1))
1376 self.assertEqual(type(q), type(d1))
1377
1378 #with other type, right
1379 (p, q) = divmod(7, d1)
1380 self.assertEqual(p, Decimal('1'))
1381 self.assertEqual(q, Decimal('2'))
1382 self.assertEqual(type(p), type(d1))
1383 self.assertEqual(type(q), type(d1))
1384
1385 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001386 Decimal = self.decimal.Decimal
1387
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001388 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1389 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1390 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1391
Christian Heimes77c02eb2008-02-09 02:18:51 +00001392 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001393 # comparisons involving signaling nans signal InvalidOperation
1394
1395 # order comparisons (<, <=, >, >=) involving only quiet nans
1396 # also signal InvalidOperation
1397
1398 # equality comparisons (==, !=) involving only quiet nans
1399 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001400 Decimal = self.decimal.Decimal
1401 InvalidOperation = self.decimal.InvalidOperation
1402 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001403
Christian Heimes77c02eb2008-02-09 02:18:51 +00001404 n = Decimal('NaN')
1405 s = Decimal('sNaN')
1406 i = Decimal('Inf')
1407 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001408
1409 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1410 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1411 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1412 equality_ops = operator.eq, operator.ne
1413
1414 # results when InvalidOperation is not trapped
1415 for x, y in qnan_pairs + snan_pairs:
1416 for op in order_ops + equality_ops:
1417 got = op(x, y)
1418 expected = True if op is operator.ne else False
1419 self.assertIs(expected, got,
1420 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1421 "got {4!r}".format(
1422 expected, op.__name__, x, y, got))
1423
1424 # repeat the above, but this time trap the InvalidOperation
1425 with localcontext() as ctx:
1426 ctx.traps[InvalidOperation] = 1
1427
1428 for x, y in qnan_pairs:
1429 for op in equality_ops:
1430 got = op(x, y)
1431 expected = True if op is operator.ne else False
1432 self.assertIs(expected, got,
1433 "expected {0!r} for "
1434 "operator.{1}({2!r}, {3!r}); "
1435 "got {4!r}".format(
1436 expected, op.__name__, x, y, got))
1437
1438 for x, y in snan_pairs:
1439 for op in equality_ops:
1440 self.assertRaises(InvalidOperation, operator.eq, x, y)
1441 self.assertRaises(InvalidOperation, operator.ne, x, y)
1442
1443 for x, y in qnan_pairs + snan_pairs:
1444 for op in order_ops:
1445 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001446
Mark Dickinson84230a12010-02-18 14:49:50 +00001447 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001448 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001449
Stefan Krah1919b7e2012-03-21 18:25:23 +01001450 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001451 self.assertEqual(Decimal(1).copy_sign(-2), d)
1452 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1453
Stefan Krah1919b7e2012-03-21 18:25:23 +01001454class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1455 decimal = C
1456class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1457 decimal = P
1458
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001459# The following are two functions used to test threading in the next class
1460
1461def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001462 Decimal = cls.decimal.Decimal
1463 InvalidOperation = cls.decimal.InvalidOperation
1464 DivisionByZero = cls.decimal.DivisionByZero
1465 Overflow = cls.decimal.Overflow
1466 Underflow = cls.decimal.Underflow
1467 Inexact = cls.decimal.Inexact
1468 getcontext = cls.decimal.getcontext
1469 localcontext = cls.decimal.localcontext
1470
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001471 d1 = Decimal(1)
1472 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001473 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001474
Stefan Krah1919b7e2012-03-21 18:25:23 +01001475 cls.finish1.set()
1476 cls.synchro.wait()
1477
1478 test2 = d1/d3
1479 with localcontext() as c2:
1480 cls.assertTrue(c2.flags[Inexact])
1481 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1482 cls.assertTrue(c2.flags[DivisionByZero])
1483 with localcontext() as c3:
1484 cls.assertTrue(c3.flags[Inexact])
1485 cls.assertTrue(c3.flags[DivisionByZero])
1486 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1487 cls.assertTrue(c3.flags[InvalidOperation])
1488 del c3
1489 cls.assertFalse(c2.flags[InvalidOperation])
1490 del c2
1491
1492 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1493 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1494
1495 c1 = getcontext()
1496 cls.assertTrue(c1.flags[Inexact])
1497 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1498 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001499 return
1500
1501def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001502 Decimal = cls.decimal.Decimal
1503 InvalidOperation = cls.decimal.InvalidOperation
1504 DivisionByZero = cls.decimal.DivisionByZero
1505 Overflow = cls.decimal.Overflow
1506 Underflow = cls.decimal.Underflow
1507 Inexact = cls.decimal.Inexact
1508 getcontext = cls.decimal.getcontext
1509 localcontext = cls.decimal.localcontext
1510
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001511 d1 = Decimal(1)
1512 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001513 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001514
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001515 thiscontext = getcontext()
1516 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001517 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001518
1519 with localcontext() as c2:
1520 cls.assertTrue(c2.flags[Inexact])
1521 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1522 cls.assertTrue(c2.flags[Overflow])
1523 with localcontext(thiscontext) as c3:
1524 cls.assertTrue(c3.flags[Inexact])
1525 cls.assertFalse(c3.flags[Overflow])
1526 c3.traps[Underflow] = True
1527 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1528 cls.assertTrue(c3.flags[Underflow])
1529 del c3
1530 cls.assertFalse(c2.flags[Underflow])
1531 cls.assertFalse(c2.traps[Underflow])
1532 del c2
1533
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001534 cls.synchro.set()
1535 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001536
Stefan Krah1919b7e2012-03-21 18:25:23 +01001537 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001538 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001539
1540 cls.assertFalse(thiscontext.traps[Underflow])
1541 cls.assertTrue(thiscontext.flags[Inexact])
1542 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1543 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001544 return
1545
Stefan Krah1919b7e2012-03-21 18:25:23 +01001546class ThreadingTest(unittest.TestCase):
1547 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001548
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001549 # Take care executing this test from IDLE, there's an issue in threading
1550 # that hangs IDLE and I couldn't find it
1551
1552 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001553 DefaultContext = self.decimal.DefaultContext
1554
1555 if self.decimal == C and not self.decimal.HAVE_THREADS:
1556 self.skipTest("compiled without threading")
1557 # Test the "threading isolation" of a Context. Also test changing
1558 # the DefaultContext, which acts as a template for the thread-local
1559 # contexts.
1560 save_prec = DefaultContext.prec
1561 save_emax = DefaultContext.Emax
1562 save_emin = DefaultContext.Emin
1563 DefaultContext.prec = 24
1564 DefaultContext.Emax = 425000000
1565 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001566
1567 self.synchro = threading.Event()
1568 self.finish1 = threading.Event()
1569 self.finish2 = threading.Event()
1570
1571 th1 = threading.Thread(target=thfunc1, args=(self,))
1572 th2 = threading.Thread(target=thfunc2, args=(self,))
1573
1574 th1.start()
1575 th2.start()
1576
1577 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001578 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001579
1580 for sig in Signals[self.decimal]:
1581 self.assertFalse(DefaultContext.flags[sig])
1582
1583 DefaultContext.prec = save_prec
1584 DefaultContext.Emax = save_emax
1585 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001586 return
1587
Stefan Krah1919b7e2012-03-21 18:25:23 +01001588@unittest.skipUnless(threading, 'threading required')
1589class CThreadingTest(ThreadingTest):
1590 decimal = C
1591@unittest.skipUnless(threading, 'threading required')
1592class PyThreadingTest(ThreadingTest):
1593 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001594
Stefan Krah1919b7e2012-03-21 18:25:23 +01001595class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001596 '''Unit tests for Usability cases of Decimal.'''
1597
1598 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001599
Stefan Krah1919b7e2012-03-21 18:25:23 +01001600 Decimal = self.decimal.Decimal
1601
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001602 da = Decimal('23.42')
1603 db = Decimal('23.42')
1604 dc = Decimal('45')
1605
1606 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001607 self.assertGreater(dc, da)
1608 self.assertGreaterEqual(dc, da)
1609 self.assertLess(da, dc)
1610 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001611 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001612 self.assertNotEqual(da, dc)
1613 self.assertLessEqual(da, db)
1614 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001615
1616 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001617 self.assertGreater(dc, 23)
1618 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001619 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001620
1621 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001622 self.assertNotEqual(da, 'ugly')
1623 self.assertNotEqual(da, 32.7)
1624 self.assertNotEqual(da, object())
1625 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001626
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001627 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001628 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001629 b = a[:]
1630 random.shuffle(a)
1631 a.sort()
1632 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001633
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001634 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001635 Decimal = self.decimal.Decimal
1636
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001637 da = Decimal('0.25')
1638 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001639 self.assertLess(da, 3.0)
1640 self.assertLessEqual(da, 3.0)
1641 self.assertGreater(db, 0.25)
1642 self.assertGreaterEqual(db, 0.25)
1643 self.assertNotEqual(da, 1.5)
1644 self.assertEqual(da, 0.25)
1645 self.assertGreater(3.0, da)
1646 self.assertGreaterEqual(3.0, da)
1647 self.assertLess(0.25, db)
1648 self.assertLessEqual(0.25, db)
1649 self.assertNotEqual(0.25, db)
1650 self.assertEqual(3.0, db)
1651 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001652
Stefan Krah1919b7e2012-03-21 18:25:23 +01001653 def test_decimal_complex_comparison(self):
1654 Decimal = self.decimal.Decimal
1655
1656 da = Decimal('0.25')
1657 db = Decimal('3.0')
1658 self.assertNotEqual(da, (1.5+0j))
1659 self.assertNotEqual((1.5+0j), da)
1660 self.assertEqual(da, (0.25+0j))
1661 self.assertEqual((0.25+0j), da)
1662 self.assertEqual((3.0+0j), db)
1663 self.assertEqual(db, (3.0+0j))
1664
1665 self.assertNotEqual(db, (3.0+1j))
1666 self.assertNotEqual((3.0+1j), db)
1667
1668 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1669 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1670 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1671 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1672
1673 def test_decimal_fraction_comparison(self):
1674 D = self.decimal.Decimal
1675 F = fractions[self.decimal].Fraction
1676 Context = self.decimal.Context
1677 localcontext = self.decimal.localcontext
1678 InvalidOperation = self.decimal.InvalidOperation
1679
1680
1681 emax = C.MAX_EMAX if C else 999999999
1682 emin = C.MIN_EMIN if C else -999999999
1683 etiny = C.MIN_ETINY if C else -1999999997
1684 c = Context(Emax=emax, Emin=emin)
1685
1686 with localcontext(c):
1687 c.prec = emax
1688 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1689 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1690 self.assertLess(F(0,1), D("1e" + str(etiny)))
1691 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1692 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1693 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1694
1695 self.assertEqual(D("0.1"), F(1,10))
1696 self.assertEqual(F(1,10), D("0.1"))
1697
1698 c.prec = 300
1699 self.assertNotEqual(D(1)/3, F(1,3))
1700 self.assertNotEqual(F(1,3), D(1)/3)
1701
1702 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1703 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1704
1705 self.assertGreater(D('inf'), F(99999999999,123))
1706 self.assertGreater(D('inf'), F(-99999999999,123))
1707 self.assertLess(D('-inf'), F(99999999999,123))
1708 self.assertLess(D('-inf'), F(-99999999999,123))
1709
1710 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1711 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1712 self.assertNotEqual(D('nan'), F(-9,123))
1713 self.assertNotEqual(F(-9,123), D('nan'))
1714
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001715 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001716 Decimal = self.decimal.Decimal
1717
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001718 d = Decimal('43.24')
1719 c = copy.copy(d)
1720 self.assertEqual(id(c), id(d))
1721 dc = copy.deepcopy(d)
1722 self.assertEqual(id(dc), id(d))
1723
1724 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001725
1726 Decimal = self.decimal.Decimal
1727 localcontext = self.decimal.localcontext
1728
Stefan Krahdc817b22010-11-17 11:16:34 +00001729 def hashit(d):
1730 a = hash(d)
1731 b = d.__hash__()
1732 self.assertEqual(a, b)
1733 return a
1734
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001735 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001736 hashit(Decimal(23))
1737 hashit(Decimal('Infinity'))
1738 hashit(Decimal('-Infinity'))
1739 hashit(Decimal('nan123'))
1740 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001741
1742 test_values = [Decimal(sign*(2**m + n))
1743 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001744 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001745 for n in range(-10, 10)
1746 for sign in [-1, 1]]
1747 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001748 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001749 Decimal("-0"), # zeros
1750 Decimal("0.00"),
1751 Decimal("-0.000"),
1752 Decimal("0E10"),
1753 Decimal("-0E12"),
1754 Decimal("10.0"), # negative exponent
1755 Decimal("-23.00000"),
1756 Decimal("1230E100"), # positive exponent
1757 Decimal("-4.5678E50"),
1758 # a value for which hash(n) != hash(n % (2**64-1))
1759 # in Python pre-2.6
1760 Decimal(2**64 + 2**32 - 1),
1761 # selection of values which fail with the old (before
1762 # version 2.6) long.__hash__
1763 Decimal("1.634E100"),
1764 Decimal("90.697E100"),
1765 Decimal("188.83E100"),
1766 Decimal("1652.9E100"),
1767 Decimal("56531E100"),
1768 ])
1769
1770 # check that hash(d) == hash(int(d)) for integral values
1771 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001772 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001773
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001774 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001775 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001776 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001777 self.assertTrue(hashit(Decimal('Inf')))
1778 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001779
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001780 # check that the hashes of a Decimal float match when they
1781 # represent exactly the same values
1782 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1783 '34.0', '2.5', '112390.625', '-0.515625']
1784 for s in test_strings:
1785 f = float(s)
1786 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001787 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001788
Stefan Krah1919b7e2012-03-21 18:25:23 +01001789 with localcontext() as c:
1790 # check that the value of the hash doesn't depend on the
1791 # current context (issue #1757)
1792 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001793
Stefan Krah1919b7e2012-03-21 18:25:23 +01001794 c.prec = 6
1795 h1 = hashit(x)
1796 c.prec = 10
1797 h2 = hashit(x)
1798 c.prec = 16
1799 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001800
Stefan Krah1919b7e2012-03-21 18:25:23 +01001801 self.assertEqual(h1, h2)
1802 self.assertEqual(h1, h3)
1803
1804 c.prec = 10000
1805 x = 1100 ** 1248
1806 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001807
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001808 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001809 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001810
1811 d1 = Decimal('15.32')
1812 d2 = Decimal('28.5')
1813 l1 = 15
1814 l2 = 28
1815
1816 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001817 self.assertIs(min(d1,d2), d1)
1818 self.assertIs(min(d2,d1), d1)
1819 self.assertIs(max(d1,d2), d2)
1820 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001821
1822 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001823 self.assertIs(min(d1,l2), d1)
1824 self.assertIs(min(l2,d1), d1)
1825 self.assertIs(max(l1,d2), d2)
1826 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001827
1828 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001829 Decimal = self.decimal.Decimal
1830
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001831 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001832 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001833 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001834 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001835
1836 def test_tostring_methods(self):
1837 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001838 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001839
1840 d = Decimal('15.32')
1841 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001842 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001843
1844 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001845 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001846 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001847
1848 d1 = Decimal('66')
1849 d2 = Decimal('15.32')
1850
1851 #int
1852 self.assertEqual(int(d1), 66)
1853 self.assertEqual(int(d2), 15)
1854
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001855 #float
1856 self.assertEqual(float(d1), 66)
1857 self.assertEqual(float(d2), 15.32)
1858
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001859 #floor
1860 test_pairs = [
1861 ('123.00', 123),
1862 ('3.2', 3),
1863 ('3.54', 3),
1864 ('3.899', 3),
1865 ('-2.3', -3),
1866 ('-11.0', -11),
1867 ('0.0', 0),
1868 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001869 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001870 ]
1871 for d, i in test_pairs:
1872 self.assertEqual(math.floor(Decimal(d)), i)
1873 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1874 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1875 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1876 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1877 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1878
1879 #ceiling
1880 test_pairs = [
1881 ('123.00', 123),
1882 ('3.2', 4),
1883 ('3.54', 4),
1884 ('3.899', 4),
1885 ('-2.3', -2),
1886 ('-11.0', -11),
1887 ('0.0', 0),
1888 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001889 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001890 ]
1891 for d, i in test_pairs:
1892 self.assertEqual(math.ceil(Decimal(d)), i)
1893 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1894 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1895 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1896 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1897 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1898
1899 #round, single argument
1900 test_pairs = [
1901 ('123.00', 123),
1902 ('3.2', 3),
1903 ('3.54', 4),
1904 ('3.899', 4),
1905 ('-2.3', -2),
1906 ('-11.0', -11),
1907 ('0.0', 0),
1908 ('-0E3', 0),
1909 ('-3.5', -4),
1910 ('-2.5', -2),
1911 ('-1.5', -2),
1912 ('-0.5', 0),
1913 ('0.5', 0),
1914 ('1.5', 2),
1915 ('2.5', 2),
1916 ('3.5', 4),
1917 ]
1918 for d, i in test_pairs:
1919 self.assertEqual(round(Decimal(d)), i)
1920 self.assertRaises(ValueError, round, Decimal('-NaN'))
1921 self.assertRaises(ValueError, round, Decimal('sNaN'))
1922 self.assertRaises(ValueError, round, Decimal('NaN123'))
1923 self.assertRaises(OverflowError, round, Decimal('Inf'))
1924 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1925
1926 #round, two arguments; this is essentially equivalent
1927 #to quantize, which is already extensively tested
1928 test_triples = [
1929 ('123.456', -4, '0E+4'),
1930 ('123.456', -3, '0E+3'),
1931 ('123.456', -2, '1E+2'),
1932 ('123.456', -1, '1.2E+2'),
1933 ('123.456', 0, '123'),
1934 ('123.456', 1, '123.5'),
1935 ('123.456', 2, '123.46'),
1936 ('123.456', 3, '123.456'),
1937 ('123.456', 4, '123.4560'),
1938 ('123.455', 2, '123.46'),
1939 ('123.445', 2, '123.44'),
1940 ('Inf', 4, 'NaN'),
1941 ('-Inf', -23, 'NaN'),
1942 ('sNaN314', 3, 'NaN314'),
1943 ]
1944 for d, n, r in test_triples:
1945 self.assertEqual(str(round(Decimal(d), n)), r)
1946
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001947 def test_nan_to_float(self):
1948 # Test conversions of decimal NANs to float.
1949 # See http://bugs.python.org/issue15544
1950 Decimal = self.decimal.Decimal
1951 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1952 f = float(Decimal(s))
1953 self.assertTrue(math.isnan(f))
1954 sign = math.copysign(1.0, f)
1955 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1956
1957 def test_snan_to_float(self):
1958 Decimal = self.decimal.Decimal
1959 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1960 d = Decimal(s)
1961 self.assertRaises(ValueError, float, d)
1962
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001963 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001964 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001965
1966 #with zero
1967 d = Decimal( (0, (0,), 0) )
1968 self.assertEqual(d, eval(repr(d)))
1969
1970 #int
1971 d = Decimal( (1, (4, 5), 0) )
1972 self.assertEqual(d, eval(repr(d)))
1973
1974 #float
1975 d = Decimal( (0, (4, 5, 3, 4), -2) )
1976 self.assertEqual(d, eval(repr(d)))
1977
1978 #weird
1979 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1980 self.assertEqual(d, eval(repr(d)))
1981
1982 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001983 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001984
1985 #with zero
1986 d = Decimal(0)
1987 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1988
1989 #int
1990 d = Decimal(-45)
1991 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1992
1993 #complicated string
1994 d = Decimal("-4.34913534E-17")
1995 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1996
Stefan Krah76e12172012-09-10 19:34:58 +02001997 # The '0' coefficient is implementation specific to decimal.py.
1998 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001999 d = Decimal("Infinity")
2000 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2001
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002002 #leading zeros in coefficient should be stripped
2003 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2004 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2005 d = Decimal( (1, (0, 0, 0), 37) )
2006 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2007 d = Decimal( (1, (), 37) )
2008 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2009
2010 #leading zeros in NaN diagnostic info should be stripped
2011 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2012 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2013 d = Decimal( (1, (0, 0, 0), 'N') )
2014 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2015 d = Decimal( (1, (), 'n') )
2016 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2017
Stefan Krah76e12172012-09-10 19:34:58 +02002018 # For infinities, decimal.py has always silently accepted any
2019 # coefficient tuple.
2020 d = Decimal( (0, (0,), 'F') )
2021 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2022 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2023 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2024 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2025 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002026
Stefan Krah1919b7e2012-03-21 18:25:23 +01002027 def test_subclassing(self):
2028 # Different behaviours when subclassing Decimal
2029 Decimal = self.decimal.Decimal
2030
2031 class MyDecimal(Decimal):
2032 pass
2033
2034 d1 = MyDecimal(1)
2035 d2 = MyDecimal(2)
2036 d = d1 + d2
2037 self.assertIs(type(d), Decimal)
2038
2039 d = d1.max(d2)
2040 self.assertIs(type(d), Decimal)
2041
2042 d = copy.copy(d1)
2043 self.assertIs(type(d), MyDecimal)
2044 self.assertEqual(d, d1)
2045
2046 d = copy.deepcopy(d1)
2047 self.assertIs(type(d), MyDecimal)
2048 self.assertEqual(d, d1)
2049
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002050 a = Decimal('1.0')
2051 b = MyDecimal(a)
2052 self.assertIs(type(b), MyDecimal)
2053 self.assertEqual(a, b)
2054
Stefan Krahed16eff2012-11-07 23:47:19 +01002055 c = Decimal(b)
2056 self.assertIs(type(c), Decimal)
2057 self.assertEqual(a, c)
2058
Stefan Krah1919b7e2012-03-21 18:25:23 +01002059 def test_implicit_context(self):
2060 Decimal = self.decimal.Decimal
2061 getcontext = self.decimal.getcontext
2062
2063 # Check results when context given implicitly. (Issue 2478)
2064 c = getcontext()
2065 self.assertEqual(str(Decimal(0).sqrt()),
2066 str(c.sqrt(Decimal(0))))
2067
2068 def test_conversions_from_int(self):
2069 # Check that methods taking a second Decimal argument will
2070 # always accept an integer in place of a Decimal.
2071 Decimal = self.decimal.Decimal
2072
2073 self.assertEqual(Decimal(4).compare(3),
2074 Decimal(4).compare(Decimal(3)))
2075 self.assertEqual(Decimal(4).compare_signal(3),
2076 Decimal(4).compare_signal(Decimal(3)))
2077 self.assertEqual(Decimal(4).compare_total(3),
2078 Decimal(4).compare_total(Decimal(3)))
2079 self.assertEqual(Decimal(4).compare_total_mag(3),
2080 Decimal(4).compare_total_mag(Decimal(3)))
2081 self.assertEqual(Decimal(10101).logical_and(1001),
2082 Decimal(10101).logical_and(Decimal(1001)))
2083 self.assertEqual(Decimal(10101).logical_or(1001),
2084 Decimal(10101).logical_or(Decimal(1001)))
2085 self.assertEqual(Decimal(10101).logical_xor(1001),
2086 Decimal(10101).logical_xor(Decimal(1001)))
2087 self.assertEqual(Decimal(567).max(123),
2088 Decimal(567).max(Decimal(123)))
2089 self.assertEqual(Decimal(567).max_mag(123),
2090 Decimal(567).max_mag(Decimal(123)))
2091 self.assertEqual(Decimal(567).min(123),
2092 Decimal(567).min(Decimal(123)))
2093 self.assertEqual(Decimal(567).min_mag(123),
2094 Decimal(567).min_mag(Decimal(123)))
2095 self.assertEqual(Decimal(567).next_toward(123),
2096 Decimal(567).next_toward(Decimal(123)))
2097 self.assertEqual(Decimal(1234).quantize(100),
2098 Decimal(1234).quantize(Decimal(100)))
2099 self.assertEqual(Decimal(768).remainder_near(1234),
2100 Decimal(768).remainder_near(Decimal(1234)))
2101 self.assertEqual(Decimal(123).rotate(1),
2102 Decimal(123).rotate(Decimal(1)))
2103 self.assertEqual(Decimal(1234).same_quantum(1000),
2104 Decimal(1234).same_quantum(Decimal(1000)))
2105 self.assertEqual(Decimal('9.123').scaleb(-100),
2106 Decimal('9.123').scaleb(Decimal(-100)))
2107 self.assertEqual(Decimal(456).shift(-1),
2108 Decimal(456).shift(Decimal(-1)))
2109
2110 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2111 Decimal(-12).fma(Decimal(45), Decimal(67)))
2112 self.assertEqual(Decimal(-12).fma(45, 67),
2113 Decimal(-12).fma(Decimal(45), Decimal(67)))
2114 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2115 Decimal(-12).fma(Decimal(45), Decimal(67)))
2116
2117class CUsabilityTest(UsabilityTest):
2118 decimal = C
2119class PyUsabilityTest(UsabilityTest):
2120 decimal = P
2121
2122class PythonAPItests(unittest.TestCase):
2123
2124 def test_abc(self):
2125 Decimal = self.decimal.Decimal
2126
2127 self.assertTrue(issubclass(Decimal, numbers.Number))
2128 self.assertFalse(issubclass(Decimal, numbers.Real))
2129 self.assertIsInstance(Decimal(0), numbers.Number)
2130 self.assertNotIsInstance(Decimal(0), numbers.Real)
2131
2132 def test_pickle(self):
2133 Decimal = self.decimal.Decimal
2134
2135 savedecimal = sys.modules['decimal']
2136
2137 # Round trip
2138 sys.modules['decimal'] = self.decimal
2139 d = Decimal('-3.141590000')
2140 p = pickle.dumps(d)
2141 e = pickle.loads(p)
2142 self.assertEqual(d, e)
2143
2144 if C:
2145 # Test interchangeability
2146 x = C.Decimal('-3.123e81723')
2147 y = P.Decimal('-3.123e81723')
2148
2149 sys.modules['decimal'] = C
2150 sx = pickle.dumps(x)
2151 sys.modules['decimal'] = P
2152 r = pickle.loads(sx)
2153 self.assertIsInstance(r, P.Decimal)
2154 self.assertEqual(r, y)
2155
2156 sys.modules['decimal'] = P
2157 sy = pickle.dumps(y)
2158 sys.modules['decimal'] = C
2159 r = pickle.loads(sy)
2160 self.assertIsInstance(r, C.Decimal)
2161 self.assertEqual(r, x)
2162
2163 sys.modules['decimal'] = savedecimal
2164
2165 def test_int(self):
2166 Decimal = self.decimal.Decimal
2167 ROUND_DOWN = self.decimal.ROUND_DOWN
2168
2169 for x in range(-250, 250):
2170 s = '%0.2f' % (x / 100.0)
2171 # should work the same as for floats
2172 self.assertEqual(int(Decimal(s)), int(float(s)))
2173 # should work the same as to_integral in the ROUND_DOWN mode
2174 d = Decimal(s)
2175 r = d.to_integral(ROUND_DOWN)
2176 self.assertEqual(Decimal(int(d)), r)
2177
2178 self.assertRaises(ValueError, int, Decimal('-nan'))
2179 self.assertRaises(ValueError, int, Decimal('snan'))
2180 self.assertRaises(OverflowError, int, Decimal('inf'))
2181 self.assertRaises(OverflowError, int, Decimal('-inf'))
2182
2183 def test_trunc(self):
2184 Decimal = self.decimal.Decimal
2185 ROUND_DOWN = self.decimal.ROUND_DOWN
2186
2187 for x in range(-250, 250):
2188 s = '%0.2f' % (x / 100.0)
2189 # should work the same as for floats
2190 self.assertEqual(int(Decimal(s)), int(float(s)))
2191 # should work the same as to_integral in the ROUND_DOWN mode
2192 d = Decimal(s)
2193 r = d.to_integral(ROUND_DOWN)
2194 self.assertEqual(Decimal(math.trunc(d)), r)
2195
2196 def test_from_float(self):
2197
2198 Decimal = self.decimal.Decimal
2199
2200 class MyDecimal(Decimal):
2201 pass
2202
2203 self.assertTrue(issubclass(MyDecimal, Decimal))
2204
2205 r = MyDecimal.from_float(0.1)
2206 self.assertEqual(type(r), MyDecimal)
2207 self.assertEqual(str(r),
2208 '0.1000000000000000055511151231257827021181583404541015625')
2209 bigint = 12345678901234567890123456789
2210 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2211 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2212 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2213 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2214 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2215 str(Decimal('NaN')))
2216 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2217 str(Decimal('Infinity')))
2218 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2219 str(Decimal('-Infinity')))
2220 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2221 for i in range(200):
2222 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2223 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2224
2225 def test_create_decimal_from_float(self):
2226 Decimal = self.decimal.Decimal
2227 Context = self.decimal.Context
2228 ROUND_DOWN = self.decimal.ROUND_DOWN
2229 ROUND_UP = self.decimal.ROUND_UP
2230 Inexact = self.decimal.Inexact
2231
2232 context = Context(prec=5, rounding=ROUND_DOWN)
2233 self.assertEqual(
2234 context.create_decimal_from_float(math.pi),
2235 Decimal('3.1415')
2236 )
2237 context = Context(prec=5, rounding=ROUND_UP)
2238 self.assertEqual(
2239 context.create_decimal_from_float(math.pi),
2240 Decimal('3.1416')
2241 )
2242 context = Context(prec=5, traps=[Inexact])
2243 self.assertRaises(
2244 Inexact,
2245 context.create_decimal_from_float,
2246 math.pi
2247 )
2248 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2249 "Decimal('-0')")
2250 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2251 "Decimal('1')")
2252 self.assertEqual(repr(context.create_decimal_from_float(10)),
2253 "Decimal('10')")
2254
2255 def test_quantize(self):
2256 Decimal = self.decimal.Decimal
2257 Context = self.decimal.Context
2258 InvalidOperation = self.decimal.InvalidOperation
2259 ROUND_DOWN = self.decimal.ROUND_DOWN
2260
2261 c = Context(Emax=99999, Emin=-99999)
2262 self.assertEqual(
2263 Decimal('7.335').quantize(Decimal('.01')),
2264 Decimal('7.34')
2265 )
2266 self.assertEqual(
2267 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2268 Decimal('7.33')
2269 )
2270 self.assertRaises(
2271 InvalidOperation,
2272 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2273 )
2274
2275 c = Context()
2276 d = Decimal("0.871831e800")
2277 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2278 self.assertEqual(x, Decimal('8.71E+799'))
2279
2280 def test_complex(self):
2281 Decimal = self.decimal.Decimal
2282
2283 x = Decimal("9.8182731e181273")
2284 self.assertEqual(x.real, x)
2285 self.assertEqual(x.imag, 0)
2286 self.assertEqual(x.conjugate(), x)
2287
2288 x = Decimal("1")
2289 self.assertEqual(complex(x), complex(float(1)))
2290
2291 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2292 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2293 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2294 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2295
2296 def test_named_parameters(self):
2297 D = self.decimal.Decimal
2298 Context = self.decimal.Context
2299 localcontext = self.decimal.localcontext
2300 InvalidOperation = self.decimal.InvalidOperation
2301 Overflow = self.decimal.Overflow
2302
2303 xc = Context()
2304 xc.prec = 1
2305 xc.Emax = 1
2306 xc.Emin = -1
2307
2308 with localcontext() as c:
2309 c.clear_flags()
2310
2311 self.assertEqual(D(9, xc), 9)
2312 self.assertEqual(D(9, context=xc), 9)
2313 self.assertEqual(D(context=xc, value=9), 9)
2314 self.assertEqual(D(context=xc), 0)
2315 xc.clear_flags()
2316 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2317 self.assertTrue(xc.flags[InvalidOperation])
2318 self.assertFalse(c.flags[InvalidOperation])
2319
2320 xc.clear_flags()
2321 self.assertEqual(D(2).exp(context=xc), 7)
2322 self.assertRaises(Overflow, D(8).exp, context=xc)
2323 self.assertTrue(xc.flags[Overflow])
2324 self.assertFalse(c.flags[Overflow])
2325
2326 xc.clear_flags()
2327 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2328 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2329 self.assertTrue(xc.flags[InvalidOperation])
2330 self.assertFalse(c.flags[InvalidOperation])
2331
2332 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2333 self.assertEqual(D(-1).next_minus(context=xc), -2)
2334 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2335 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2336 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2337 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2338 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2339 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2340
2341 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2342 xc.clear_flags()
2343 self.assertRaises(InvalidOperation,
2344 D("0").compare_signal, D('nan'), context=xc)
2345 self.assertTrue(xc.flags[InvalidOperation])
2346 self.assertFalse(c.flags[InvalidOperation])
2347 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2348 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2349 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2350 D('-0.3'))
2351 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2352 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2353 D('0.0'))
2354 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2355 xc.clear_flags()
2356 self.assertRaises(InvalidOperation,
2357 D("0.2").quantize, D('1e10'), context=xc)
2358 self.assertTrue(xc.flags[InvalidOperation])
2359 self.assertFalse(c.flags[InvalidOperation])
2360 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2361 D('-0.5'))
2362
2363 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2364 D('7E+1'))
2365
2366 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2367 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2368 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2369 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2370 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2371 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2372 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2373 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2374
2375 self.assertFalse(D("0.01").is_normal(context=xc))
2376 self.assertTrue(D("0.01").is_subnormal(context=xc))
2377
2378 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2379 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2380 self.assertRaises(TypeError, D(1).radix, context=xc)
2381
2382 self.assertEqual(D(-111).logb(context=xc), 2)
2383 self.assertEqual(D(0).logical_invert(context=xc), 1)
2384 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2385 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2386
2387 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2388 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2389 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2390 self.assertEqual(D('23').rotate(1, context=xc), 3)
2391 self.assertEqual(D('23').rotate(1, context=xc), 3)
2392 xc.clear_flags()
2393 self.assertRaises(Overflow,
2394 D('23').scaleb, 1, context=xc)
2395 self.assertTrue(xc.flags[Overflow])
2396 self.assertFalse(c.flags[Overflow])
2397 self.assertEqual(D('23').shift(-1, context=xc), 0)
2398
2399 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2400 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2401
2402 if (self.decimal == C):
2403 self.assertRaises(TypeError, D(1).canonical, context=xc)
2404 self.assertEqual(D("-1").copy_abs(context=xc), 1)
2405 self.assertEqual(D("1").copy_negate(context=xc), -1)
2406 else:
2407 self.assertEqual(D(1).canonical(context=xc), 1)
2408 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2409 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2410
Stefan Krahb6405ef2012-03-23 14:46:48 +01002411 def test_exception_hierarchy(self):
2412
2413 decimal = self.decimal
2414 DecimalException = decimal.DecimalException
2415 InvalidOperation = decimal.InvalidOperation
2416 FloatOperation = decimal.FloatOperation
2417 DivisionByZero = decimal.DivisionByZero
2418 Overflow = decimal.Overflow
2419 Underflow = decimal.Underflow
2420 Subnormal = decimal.Subnormal
2421 Inexact = decimal.Inexact
2422 Rounded = decimal.Rounded
2423 Clamped = decimal.Clamped
2424
2425 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2426
2427 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2428 self.assertTrue(issubclass(FloatOperation, DecimalException))
2429 self.assertTrue(issubclass(FloatOperation, TypeError))
2430 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2431 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2432 self.assertTrue(issubclass(Overflow, Rounded))
2433 self.assertTrue(issubclass(Overflow, Inexact))
2434 self.assertTrue(issubclass(Overflow, DecimalException))
2435 self.assertTrue(issubclass(Underflow, Inexact))
2436 self.assertTrue(issubclass(Underflow, Rounded))
2437 self.assertTrue(issubclass(Underflow, Subnormal))
2438 self.assertTrue(issubclass(Underflow, DecimalException))
2439
2440 self.assertTrue(issubclass(Subnormal, DecimalException))
2441 self.assertTrue(issubclass(Inexact, DecimalException))
2442 self.assertTrue(issubclass(Rounded, DecimalException))
2443 self.assertTrue(issubclass(Clamped, DecimalException))
2444
2445 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2446 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2447 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2448 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2449 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2450
Stefan Krah1919b7e2012-03-21 18:25:23 +01002451class CPythonAPItests(PythonAPItests):
2452 decimal = C
2453class PyPythonAPItests(PythonAPItests):
2454 decimal = P
2455
2456class ContextAPItests(unittest.TestCase):
2457
2458 def test_pickle(self):
2459
2460 Context = self.decimal.Context
2461
2462 savedecimal = sys.modules['decimal']
2463
2464 # Round trip
2465 sys.modules['decimal'] = self.decimal
2466 c = Context()
2467 e = pickle.loads(pickle.dumps(c))
2468
2469 self.assertEqual(c.prec, e.prec)
2470 self.assertEqual(c.Emin, e.Emin)
2471 self.assertEqual(c.Emax, e.Emax)
2472 self.assertEqual(c.rounding, e.rounding)
2473 self.assertEqual(c.capitals, e.capitals)
2474 self.assertEqual(c.clamp, e.clamp)
2475 self.assertEqual(c.flags, e.flags)
2476 self.assertEqual(c.traps, e.traps)
2477
2478 # Test interchangeability
2479 combinations = [(C, P), (P, C)] if C else [(P, P)]
2480 for dumper, loader in combinations:
2481 for ri, _ in enumerate(RoundingModes[dumper]):
2482 for fi, _ in enumerate(OrderedSignals[dumper]):
2483 for ti, _ in enumerate(OrderedSignals[dumper]):
2484
2485 prec = random.randrange(1, 100)
2486 emin = random.randrange(-100, 0)
2487 emax = random.randrange(1, 100)
2488 caps = random.randrange(2)
2489 clamp = random.randrange(2)
2490
2491 # One module dumps
2492 sys.modules['decimal'] = dumper
2493 c = dumper.Context(
2494 prec=prec, Emin=emin, Emax=emax,
2495 rounding=RoundingModes[dumper][ri],
2496 capitals=caps, clamp=clamp,
2497 flags=OrderedSignals[dumper][:fi],
2498 traps=OrderedSignals[dumper][:ti]
2499 )
2500 s = pickle.dumps(c)
2501
2502 # The other module loads
2503 sys.modules['decimal'] = loader
2504 d = pickle.loads(s)
2505 self.assertIsInstance(d, loader.Context)
2506
2507 self.assertEqual(d.prec, prec)
2508 self.assertEqual(d.Emin, emin)
2509 self.assertEqual(d.Emax, emax)
2510 self.assertEqual(d.rounding, RoundingModes[loader][ri])
2511 self.assertEqual(d.capitals, caps)
2512 self.assertEqual(d.clamp, clamp)
2513 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2514 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2515
2516 sys.modules['decimal'] = savedecimal
2517
2518 def test_equality_with_other_types(self):
2519 Decimal = self.decimal.Decimal
2520
2521 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2522 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2523
2524 def test_copy(self):
2525 # All copies should be deep
2526 Decimal = self.decimal.Decimal
2527 Context = self.decimal.Context
2528
2529 c = Context()
2530 d = c.copy()
2531 self.assertNotEqual(id(c), id(d))
2532 self.assertNotEqual(id(c.flags), id(d.flags))
2533 self.assertNotEqual(id(c.traps), id(d.traps))
2534 k1 = set(c.flags.keys())
2535 k2 = set(d.flags.keys())
2536 self.assertEqual(k1, k2)
2537 self.assertEqual(c.flags, d.flags)
2538
2539 def test__clamp(self):
2540 # In Python 3.2, the private attribute `_clamp` was made
2541 # public (issue 8540), with the old `_clamp` becoming a
2542 # property wrapping `clamp`. For the duration of Python 3.2
2543 # only, the attribute should be gettable/settable via both
2544 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2545 # removed.
2546 Context = self.decimal.Context
2547 c = Context()
2548 self.assertRaises(AttributeError, getattr, c, '_clamp')
2549
2550 def test_abs(self):
2551 Decimal = self.decimal.Decimal
2552 Context = self.decimal.Context
2553
2554 c = Context()
2555 d = c.abs(Decimal(-1))
2556 self.assertEqual(c.abs(-1), d)
2557 self.assertRaises(TypeError, c.abs, '-1')
2558
2559 def test_add(self):
2560 Decimal = self.decimal.Decimal
2561 Context = self.decimal.Context
2562
2563 c = Context()
2564 d = c.add(Decimal(1), Decimal(1))
2565 self.assertEqual(c.add(1, 1), d)
2566 self.assertEqual(c.add(Decimal(1), 1), d)
2567 self.assertEqual(c.add(1, Decimal(1)), d)
2568 self.assertRaises(TypeError, c.add, '1', 1)
2569 self.assertRaises(TypeError, c.add, 1, '1')
2570
2571 def test_compare(self):
2572 Decimal = self.decimal.Decimal
2573 Context = self.decimal.Context
2574
2575 c = Context()
2576 d = c.compare(Decimal(1), Decimal(1))
2577 self.assertEqual(c.compare(1, 1), d)
2578 self.assertEqual(c.compare(Decimal(1), 1), d)
2579 self.assertEqual(c.compare(1, Decimal(1)), d)
2580 self.assertRaises(TypeError, c.compare, '1', 1)
2581 self.assertRaises(TypeError, c.compare, 1, '1')
2582
2583 def test_compare_signal(self):
2584 Decimal = self.decimal.Decimal
2585 Context = self.decimal.Context
2586
2587 c = Context()
2588 d = c.compare_signal(Decimal(1), Decimal(1))
2589 self.assertEqual(c.compare_signal(1, 1), d)
2590 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2591 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2592 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2593 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2594
2595 def test_compare_total(self):
2596 Decimal = self.decimal.Decimal
2597 Context = self.decimal.Context
2598
2599 c = Context()
2600 d = c.compare_total(Decimal(1), Decimal(1))
2601 self.assertEqual(c.compare_total(1, 1), d)
2602 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2603 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2604 self.assertRaises(TypeError, c.compare_total, '1', 1)
2605 self.assertRaises(TypeError, c.compare_total, 1, '1')
2606
2607 def test_compare_total_mag(self):
2608 Decimal = self.decimal.Decimal
2609 Context = self.decimal.Context
2610
2611 c = Context()
2612 d = c.compare_total_mag(Decimal(1), Decimal(1))
2613 self.assertEqual(c.compare_total_mag(1, 1), d)
2614 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2615 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2616 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2617 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2618
2619 def test_copy_abs(self):
2620 Decimal = self.decimal.Decimal
2621 Context = self.decimal.Context
2622
2623 c = Context()
2624 d = c.copy_abs(Decimal(-1))
2625 self.assertEqual(c.copy_abs(-1), d)
2626 self.assertRaises(TypeError, c.copy_abs, '-1')
2627
2628 def test_copy_decimal(self):
2629 Decimal = self.decimal.Decimal
2630 Context = self.decimal.Context
2631
2632 c = Context()
2633 d = c.copy_decimal(Decimal(-1))
2634 self.assertEqual(c.copy_decimal(-1), d)
2635 self.assertRaises(TypeError, c.copy_decimal, '-1')
2636
2637 def test_copy_negate(self):
2638 Decimal = self.decimal.Decimal
2639 Context = self.decimal.Context
2640
2641 c = Context()
2642 d = c.copy_negate(Decimal(-1))
2643 self.assertEqual(c.copy_negate(-1), d)
2644 self.assertRaises(TypeError, c.copy_negate, '-1')
2645
2646 def test_copy_sign(self):
2647 Decimal = self.decimal.Decimal
2648 Context = self.decimal.Context
2649
2650 c = Context()
2651 d = c.copy_sign(Decimal(1), Decimal(-2))
2652 self.assertEqual(c.copy_sign(1, -2), d)
2653 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2654 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2655 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2656 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2657
2658 def test_divide(self):
2659 Decimal = self.decimal.Decimal
2660 Context = self.decimal.Context
2661
2662 c = Context()
2663 d = c.divide(Decimal(1), Decimal(2))
2664 self.assertEqual(c.divide(1, 2), d)
2665 self.assertEqual(c.divide(Decimal(1), 2), d)
2666 self.assertEqual(c.divide(1, Decimal(2)), d)
2667 self.assertRaises(TypeError, c.divide, '1', 2)
2668 self.assertRaises(TypeError, c.divide, 1, '2')
2669
2670 def test_divide_int(self):
2671 Decimal = self.decimal.Decimal
2672 Context = self.decimal.Context
2673
2674 c = Context()
2675 d = c.divide_int(Decimal(1), Decimal(2))
2676 self.assertEqual(c.divide_int(1, 2), d)
2677 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2678 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2679 self.assertRaises(TypeError, c.divide_int, '1', 2)
2680 self.assertRaises(TypeError, c.divide_int, 1, '2')
2681
2682 def test_divmod(self):
2683 Decimal = self.decimal.Decimal
2684 Context = self.decimal.Context
2685
2686 c = Context()
2687 d = c.divmod(Decimal(1), Decimal(2))
2688 self.assertEqual(c.divmod(1, 2), d)
2689 self.assertEqual(c.divmod(Decimal(1), 2), d)
2690 self.assertEqual(c.divmod(1, Decimal(2)), d)
2691 self.assertRaises(TypeError, c.divmod, '1', 2)
2692 self.assertRaises(TypeError, c.divmod, 1, '2')
2693
2694 def test_exp(self):
2695 Decimal = self.decimal.Decimal
2696 Context = self.decimal.Context
2697
2698 c = Context()
2699 d = c.exp(Decimal(10))
2700 self.assertEqual(c.exp(10), d)
2701 self.assertRaises(TypeError, c.exp, '10')
2702
2703 def test_fma(self):
2704 Decimal = self.decimal.Decimal
2705 Context = self.decimal.Context
2706
2707 c = Context()
2708 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
2709 self.assertEqual(c.fma(2, 3, 4), d)
2710 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
2711 self.assertEqual(c.fma(2, Decimal(3), 4), d)
2712 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
2713 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
2714 self.assertRaises(TypeError, c.fma, '2', 3, 4)
2715 self.assertRaises(TypeError, c.fma, 2, '3', 4)
2716 self.assertRaises(TypeError, c.fma, 2, 3, '4')
2717
2718 # Issue 12079 for Context.fma ...
2719 self.assertRaises(TypeError, c.fma,
2720 Decimal('Infinity'), Decimal(0), "not a decimal")
2721 self.assertRaises(TypeError, c.fma,
2722 Decimal(1), Decimal('snan'), 1.222)
2723 # ... and for Decimal.fma.
2724 self.assertRaises(TypeError, Decimal('Infinity').fma,
2725 Decimal(0), "not a decimal")
2726 self.assertRaises(TypeError, Decimal(1).fma,
2727 Decimal('snan'), 1.222)
2728
2729 def test_is_finite(self):
2730 Decimal = self.decimal.Decimal
2731 Context = self.decimal.Context
2732
2733 c = Context()
2734 d = c.is_finite(Decimal(10))
2735 self.assertEqual(c.is_finite(10), d)
2736 self.assertRaises(TypeError, c.is_finite, '10')
2737
2738 def test_is_infinite(self):
2739 Decimal = self.decimal.Decimal
2740 Context = self.decimal.Context
2741
2742 c = Context()
2743 d = c.is_infinite(Decimal(10))
2744 self.assertEqual(c.is_infinite(10), d)
2745 self.assertRaises(TypeError, c.is_infinite, '10')
2746
2747 def test_is_nan(self):
2748 Decimal = self.decimal.Decimal
2749 Context = self.decimal.Context
2750
2751 c = Context()
2752 d = c.is_nan(Decimal(10))
2753 self.assertEqual(c.is_nan(10), d)
2754 self.assertRaises(TypeError, c.is_nan, '10')
2755
2756 def test_is_normal(self):
2757 Decimal = self.decimal.Decimal
2758 Context = self.decimal.Context
2759
2760 c = Context()
2761 d = c.is_normal(Decimal(10))
2762 self.assertEqual(c.is_normal(10), d)
2763 self.assertRaises(TypeError, c.is_normal, '10')
2764
2765 def test_is_qnan(self):
2766 Decimal = self.decimal.Decimal
2767 Context = self.decimal.Context
2768
2769 c = Context()
2770 d = c.is_qnan(Decimal(10))
2771 self.assertEqual(c.is_qnan(10), d)
2772 self.assertRaises(TypeError, c.is_qnan, '10')
2773
2774 def test_is_signed(self):
2775 Decimal = self.decimal.Decimal
2776 Context = self.decimal.Context
2777
2778 c = Context()
2779 d = c.is_signed(Decimal(10))
2780 self.assertEqual(c.is_signed(10), d)
2781 self.assertRaises(TypeError, c.is_signed, '10')
2782
2783 def test_is_snan(self):
2784 Decimal = self.decimal.Decimal
2785 Context = self.decimal.Context
2786
2787 c = Context()
2788 d = c.is_snan(Decimal(10))
2789 self.assertEqual(c.is_snan(10), d)
2790 self.assertRaises(TypeError, c.is_snan, '10')
2791
2792 def test_is_subnormal(self):
2793 Decimal = self.decimal.Decimal
2794 Context = self.decimal.Context
2795
2796 c = Context()
2797 d = c.is_subnormal(Decimal(10))
2798 self.assertEqual(c.is_subnormal(10), d)
2799 self.assertRaises(TypeError, c.is_subnormal, '10')
2800
2801 def test_is_zero(self):
2802 Decimal = self.decimal.Decimal
2803 Context = self.decimal.Context
2804
2805 c = Context()
2806 d = c.is_zero(Decimal(10))
2807 self.assertEqual(c.is_zero(10), d)
2808 self.assertRaises(TypeError, c.is_zero, '10')
2809
2810 def test_ln(self):
2811 Decimal = self.decimal.Decimal
2812 Context = self.decimal.Context
2813
2814 c = Context()
2815 d = c.ln(Decimal(10))
2816 self.assertEqual(c.ln(10), d)
2817 self.assertRaises(TypeError, c.ln, '10')
2818
2819 def test_log10(self):
2820 Decimal = self.decimal.Decimal
2821 Context = self.decimal.Context
2822
2823 c = Context()
2824 d = c.log10(Decimal(10))
2825 self.assertEqual(c.log10(10), d)
2826 self.assertRaises(TypeError, c.log10, '10')
2827
2828 def test_logb(self):
2829 Decimal = self.decimal.Decimal
2830 Context = self.decimal.Context
2831
2832 c = Context()
2833 d = c.logb(Decimal(10))
2834 self.assertEqual(c.logb(10), d)
2835 self.assertRaises(TypeError, c.logb, '10')
2836
2837 def test_logical_and(self):
2838 Decimal = self.decimal.Decimal
2839 Context = self.decimal.Context
2840
2841 c = Context()
2842 d = c.logical_and(Decimal(1), Decimal(1))
2843 self.assertEqual(c.logical_and(1, 1), d)
2844 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2845 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2846 self.assertRaises(TypeError, c.logical_and, '1', 1)
2847 self.assertRaises(TypeError, c.logical_and, 1, '1')
2848
2849 def test_logical_invert(self):
2850 Decimal = self.decimal.Decimal
2851 Context = self.decimal.Context
2852
2853 c = Context()
2854 d = c.logical_invert(Decimal(1000))
2855 self.assertEqual(c.logical_invert(1000), d)
2856 self.assertRaises(TypeError, c.logical_invert, '1000')
2857
2858 def test_logical_or(self):
2859 Decimal = self.decimal.Decimal
2860 Context = self.decimal.Context
2861
2862 c = Context()
2863 d = c.logical_or(Decimal(1), Decimal(1))
2864 self.assertEqual(c.logical_or(1, 1), d)
2865 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2866 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2867 self.assertRaises(TypeError, c.logical_or, '1', 1)
2868 self.assertRaises(TypeError, c.logical_or, 1, '1')
2869
2870 def test_logical_xor(self):
2871 Decimal = self.decimal.Decimal
2872 Context = self.decimal.Context
2873
2874 c = Context()
2875 d = c.logical_xor(Decimal(1), Decimal(1))
2876 self.assertEqual(c.logical_xor(1, 1), d)
2877 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2878 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2879 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2880 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2881
2882 def test_max(self):
2883 Decimal = self.decimal.Decimal
2884 Context = self.decimal.Context
2885
2886 c = Context()
2887 d = c.max(Decimal(1), Decimal(2))
2888 self.assertEqual(c.max(1, 2), d)
2889 self.assertEqual(c.max(Decimal(1), 2), d)
2890 self.assertEqual(c.max(1, Decimal(2)), d)
2891 self.assertRaises(TypeError, c.max, '1', 2)
2892 self.assertRaises(TypeError, c.max, 1, '2')
2893
2894 def test_max_mag(self):
2895 Decimal = self.decimal.Decimal
2896 Context = self.decimal.Context
2897
2898 c = Context()
2899 d = c.max_mag(Decimal(1), Decimal(2))
2900 self.assertEqual(c.max_mag(1, 2), d)
2901 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2902 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2903 self.assertRaises(TypeError, c.max_mag, '1', 2)
2904 self.assertRaises(TypeError, c.max_mag, 1, '2')
2905
2906 def test_min(self):
2907 Decimal = self.decimal.Decimal
2908 Context = self.decimal.Context
2909
2910 c = Context()
2911 d = c.min(Decimal(1), Decimal(2))
2912 self.assertEqual(c.min(1, 2), d)
2913 self.assertEqual(c.min(Decimal(1), 2), d)
2914 self.assertEqual(c.min(1, Decimal(2)), d)
2915 self.assertRaises(TypeError, c.min, '1', 2)
2916 self.assertRaises(TypeError, c.min, 1, '2')
2917
2918 def test_min_mag(self):
2919 Decimal = self.decimal.Decimal
2920 Context = self.decimal.Context
2921
2922 c = Context()
2923 d = c.min_mag(Decimal(1), Decimal(2))
2924 self.assertEqual(c.min_mag(1, 2), d)
2925 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2926 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2927 self.assertRaises(TypeError, c.min_mag, '1', 2)
2928 self.assertRaises(TypeError, c.min_mag, 1, '2')
2929
2930 def test_minus(self):
2931 Decimal = self.decimal.Decimal
2932 Context = self.decimal.Context
2933
2934 c = Context()
2935 d = c.minus(Decimal(10))
2936 self.assertEqual(c.minus(10), d)
2937 self.assertRaises(TypeError, c.minus, '10')
2938
2939 def test_multiply(self):
2940 Decimal = self.decimal.Decimal
2941 Context = self.decimal.Context
2942
2943 c = Context()
2944 d = c.multiply(Decimal(1), Decimal(2))
2945 self.assertEqual(c.multiply(1, 2), d)
2946 self.assertEqual(c.multiply(Decimal(1), 2), d)
2947 self.assertEqual(c.multiply(1, Decimal(2)), d)
2948 self.assertRaises(TypeError, c.multiply, '1', 2)
2949 self.assertRaises(TypeError, c.multiply, 1, '2')
2950
2951 def test_next_minus(self):
2952 Decimal = self.decimal.Decimal
2953 Context = self.decimal.Context
2954
2955 c = Context()
2956 d = c.next_minus(Decimal(10))
2957 self.assertEqual(c.next_minus(10), d)
2958 self.assertRaises(TypeError, c.next_minus, '10')
2959
2960 def test_next_plus(self):
2961 Decimal = self.decimal.Decimal
2962 Context = self.decimal.Context
2963
2964 c = Context()
2965 d = c.next_plus(Decimal(10))
2966 self.assertEqual(c.next_plus(10), d)
2967 self.assertRaises(TypeError, c.next_plus, '10')
2968
2969 def test_next_toward(self):
2970 Decimal = self.decimal.Decimal
2971 Context = self.decimal.Context
2972
2973 c = Context()
2974 d = c.next_toward(Decimal(1), Decimal(2))
2975 self.assertEqual(c.next_toward(1, 2), d)
2976 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2977 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2978 self.assertRaises(TypeError, c.next_toward, '1', 2)
2979 self.assertRaises(TypeError, c.next_toward, 1, '2')
2980
2981 def test_normalize(self):
2982 Decimal = self.decimal.Decimal
2983 Context = self.decimal.Context
2984
2985 c = Context()
2986 d = c.normalize(Decimal(10))
2987 self.assertEqual(c.normalize(10), d)
2988 self.assertRaises(TypeError, c.normalize, '10')
2989
2990 def test_number_class(self):
2991 Decimal = self.decimal.Decimal
2992 Context = self.decimal.Context
2993
2994 c = Context()
2995 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2996 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2997 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2998
2999 def test_plus(self):
3000 Decimal = self.decimal.Decimal
3001 Context = self.decimal.Context
3002
3003 c = Context()
3004 d = c.plus(Decimal(10))
3005 self.assertEqual(c.plus(10), d)
3006 self.assertRaises(TypeError, c.plus, '10')
3007
3008 def test_power(self):
3009 Decimal = self.decimal.Decimal
3010 Context = self.decimal.Context
3011
3012 c = Context()
3013 d = c.power(Decimal(1), Decimal(4))
3014 self.assertEqual(c.power(1, 4), d)
3015 self.assertEqual(c.power(Decimal(1), 4), d)
3016 self.assertEqual(c.power(1, Decimal(4)), d)
3017 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3018 self.assertRaises(TypeError, c.power, '1', 4)
3019 self.assertRaises(TypeError, c.power, 1, '4')
3020 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3021
3022 def test_quantize(self):
3023 Decimal = self.decimal.Decimal
3024 Context = self.decimal.Context
3025
3026 c = Context()
3027 d = c.quantize(Decimal(1), Decimal(2))
3028 self.assertEqual(c.quantize(1, 2), d)
3029 self.assertEqual(c.quantize(Decimal(1), 2), d)
3030 self.assertEqual(c.quantize(1, Decimal(2)), d)
3031 self.assertRaises(TypeError, c.quantize, '1', 2)
3032 self.assertRaises(TypeError, c.quantize, 1, '2')
3033
3034 def test_remainder(self):
3035 Decimal = self.decimal.Decimal
3036 Context = self.decimal.Context
3037
3038 c = Context()
3039 d = c.remainder(Decimal(1), Decimal(2))
3040 self.assertEqual(c.remainder(1, 2), d)
3041 self.assertEqual(c.remainder(Decimal(1), 2), d)
3042 self.assertEqual(c.remainder(1, Decimal(2)), d)
3043 self.assertRaises(TypeError, c.remainder, '1', 2)
3044 self.assertRaises(TypeError, c.remainder, 1, '2')
3045
3046 def test_remainder_near(self):
3047 Decimal = self.decimal.Decimal
3048 Context = self.decimal.Context
3049
3050 c = Context()
3051 d = c.remainder_near(Decimal(1), Decimal(2))
3052 self.assertEqual(c.remainder_near(1, 2), d)
3053 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3054 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3055 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3056 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3057
3058 def test_rotate(self):
3059 Decimal = self.decimal.Decimal
3060 Context = self.decimal.Context
3061
3062 c = Context()
3063 d = c.rotate(Decimal(1), Decimal(2))
3064 self.assertEqual(c.rotate(1, 2), d)
3065 self.assertEqual(c.rotate(Decimal(1), 2), d)
3066 self.assertEqual(c.rotate(1, Decimal(2)), d)
3067 self.assertRaises(TypeError, c.rotate, '1', 2)
3068 self.assertRaises(TypeError, c.rotate, 1, '2')
3069
3070 def test_sqrt(self):
3071 Decimal = self.decimal.Decimal
3072 Context = self.decimal.Context
3073
3074 c = Context()
3075 d = c.sqrt(Decimal(10))
3076 self.assertEqual(c.sqrt(10), d)
3077 self.assertRaises(TypeError, c.sqrt, '10')
3078
3079 def test_same_quantum(self):
3080 Decimal = self.decimal.Decimal
3081 Context = self.decimal.Context
3082
3083 c = Context()
3084 d = c.same_quantum(Decimal(1), Decimal(2))
3085 self.assertEqual(c.same_quantum(1, 2), d)
3086 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3087 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3088 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3089 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3090
3091 def test_scaleb(self):
3092 Decimal = self.decimal.Decimal
3093 Context = self.decimal.Context
3094
3095 c = Context()
3096 d = c.scaleb(Decimal(1), Decimal(2))
3097 self.assertEqual(c.scaleb(1, 2), d)
3098 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3099 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3100 self.assertRaises(TypeError, c.scaleb, '1', 2)
3101 self.assertRaises(TypeError, c.scaleb, 1, '2')
3102
3103 def test_shift(self):
3104 Decimal = self.decimal.Decimal
3105 Context = self.decimal.Context
3106
3107 c = Context()
3108 d = c.shift(Decimal(1), Decimal(2))
3109 self.assertEqual(c.shift(1, 2), d)
3110 self.assertEqual(c.shift(Decimal(1), 2), d)
3111 self.assertEqual(c.shift(1, Decimal(2)), d)
3112 self.assertRaises(TypeError, c.shift, '1', 2)
3113 self.assertRaises(TypeError, c.shift, 1, '2')
3114
3115 def test_subtract(self):
3116 Decimal = self.decimal.Decimal
3117 Context = self.decimal.Context
3118
3119 c = Context()
3120 d = c.subtract(Decimal(1), Decimal(2))
3121 self.assertEqual(c.subtract(1, 2), d)
3122 self.assertEqual(c.subtract(Decimal(1), 2), d)
3123 self.assertEqual(c.subtract(1, Decimal(2)), d)
3124 self.assertRaises(TypeError, c.subtract, '1', 2)
3125 self.assertRaises(TypeError, c.subtract, 1, '2')
3126
3127 def test_to_eng_string(self):
3128 Decimal = self.decimal.Decimal
3129 Context = self.decimal.Context
3130
3131 c = Context()
3132 d = c.to_eng_string(Decimal(10))
3133 self.assertEqual(c.to_eng_string(10), d)
3134 self.assertRaises(TypeError, c.to_eng_string, '10')
3135
3136 def test_to_sci_string(self):
3137 Decimal = self.decimal.Decimal
3138 Context = self.decimal.Context
3139
3140 c = Context()
3141 d = c.to_sci_string(Decimal(10))
3142 self.assertEqual(c.to_sci_string(10), d)
3143 self.assertRaises(TypeError, c.to_sci_string, '10')
3144
3145 def test_to_integral_exact(self):
3146 Decimal = self.decimal.Decimal
3147 Context = self.decimal.Context
3148
3149 c = Context()
3150 d = c.to_integral_exact(Decimal(10))
3151 self.assertEqual(c.to_integral_exact(10), d)
3152 self.assertRaises(TypeError, c.to_integral_exact, '10')
3153
3154 def test_to_integral_value(self):
3155 Decimal = self.decimal.Decimal
3156 Context = self.decimal.Context
3157
3158 c = Context()
3159 d = c.to_integral_value(Decimal(10))
3160 self.assertEqual(c.to_integral_value(10), d)
3161 self.assertRaises(TypeError, c.to_integral_value, '10')
3162 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3163
3164class CContextAPItests(ContextAPItests):
3165 decimal = C
3166class PyContextAPItests(ContextAPItests):
3167 decimal = P
3168
3169class ContextWithStatement(unittest.TestCase):
3170 # Can't do these as docstrings until Python 2.6
3171 # as doctest can't handle __future__ statements
3172
3173 def test_localcontext(self):
3174 # Use a copy of the current context in the block
3175 getcontext = self.decimal.getcontext
3176 localcontext = self.decimal.localcontext
3177
3178 orig_ctx = getcontext()
3179 with localcontext() as enter_ctx:
3180 set_ctx = getcontext()
3181 final_ctx = getcontext()
3182 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3183 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3184 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3185
3186 def test_localcontextarg(self):
3187 # Use a copy of the supplied context in the block
3188 Context = self.decimal.Context
3189 getcontext = self.decimal.getcontext
3190 localcontext = self.decimal.localcontext
3191
3192 localcontext = self.decimal.localcontext
3193 orig_ctx = getcontext()
3194 new_ctx = Context(prec=42)
3195 with localcontext(new_ctx) as enter_ctx:
3196 set_ctx = getcontext()
3197 final_ctx = getcontext()
3198 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3199 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3200 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3201 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3202
3203 def test_nested_with_statements(self):
3204 # Use a copy of the supplied context in the block
3205 Decimal = self.decimal.Decimal
3206 Context = self.decimal.Context
3207 getcontext = self.decimal.getcontext
3208 localcontext = self.decimal.localcontext
3209 Clamped = self.decimal.Clamped
3210 Overflow = self.decimal.Overflow
3211
3212 orig_ctx = getcontext()
3213 orig_ctx.clear_flags()
3214 new_ctx = Context(Emax=384)
3215 with localcontext() as c1:
3216 self.assertEqual(c1.flags, orig_ctx.flags)
3217 self.assertEqual(c1.traps, orig_ctx.traps)
3218 c1.traps[Clamped] = True
3219 c1.Emin = -383
3220 self.assertNotEqual(orig_ctx.Emin, -383)
3221 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3222 self.assertTrue(c1.flags[Clamped])
3223 with localcontext(new_ctx) as c2:
3224 self.assertEqual(c2.flags, new_ctx.flags)
3225 self.assertEqual(c2.traps, new_ctx.traps)
3226 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3227 self.assertFalse(c2.flags[Clamped])
3228 self.assertTrue(c2.flags[Overflow])
3229 del c2
3230 self.assertFalse(c1.flags[Overflow])
3231 del c1
3232 self.assertNotEqual(orig_ctx.Emin, -383)
3233 self.assertFalse(orig_ctx.flags[Clamped])
3234 self.assertFalse(orig_ctx.flags[Overflow])
3235 self.assertFalse(new_ctx.flags[Clamped])
3236 self.assertFalse(new_ctx.flags[Overflow])
3237
3238 def test_with_statements_gc1(self):
3239 localcontext = self.decimal.localcontext
3240
3241 with localcontext() as c1:
3242 del c1
3243 with localcontext() as c2:
3244 del c2
3245 with localcontext() as c3:
3246 del c3
3247 with localcontext() as c4:
3248 del c4
3249
3250 def test_with_statements_gc2(self):
3251 localcontext = self.decimal.localcontext
3252
3253 with localcontext() as c1:
3254 with localcontext(c1) as c2:
3255 del c1
3256 with localcontext(c2) as c3:
3257 del c2
3258 with localcontext(c3) as c4:
3259 del c3
3260 del c4
3261
3262 def test_with_statements_gc3(self):
3263 Context = self.decimal.Context
3264 localcontext = self.decimal.localcontext
3265 getcontext = self.decimal.getcontext
3266 setcontext = self.decimal.setcontext
3267
3268 with localcontext() as c1:
3269 del c1
3270 n1 = Context(prec=1)
3271 setcontext(n1)
3272 with localcontext(n1) as c2:
3273 del n1
3274 self.assertEqual(c2.prec, 1)
3275 del c2
3276 n2 = Context(prec=2)
3277 setcontext(n2)
3278 del n2
3279 self.assertEqual(getcontext().prec, 2)
3280 n3 = Context(prec=3)
3281 setcontext(n3)
3282 self.assertEqual(getcontext().prec, 3)
3283 with localcontext(n3) as c3:
3284 del n3
3285 self.assertEqual(c3.prec, 3)
3286 del c3
3287 n4 = Context(prec=4)
3288 setcontext(n4)
3289 del n4
3290 self.assertEqual(getcontext().prec, 4)
3291 with localcontext() as c4:
3292 self.assertEqual(c4.prec, 4)
3293 del c4
3294
3295class CContextWithStatement(ContextWithStatement):
3296 decimal = C
3297class PyContextWithStatement(ContextWithStatement):
3298 decimal = P
3299
3300class ContextFlags(unittest.TestCase):
3301
3302 def test_flags_irrelevant(self):
3303 # check that the result (numeric result + flags raised) of an
3304 # arithmetic operation doesn't depend on the current flags
3305 Decimal = self.decimal.Decimal
3306 Context = self.decimal.Context
3307 Inexact = self.decimal.Inexact
3308 Rounded = self.decimal.Rounded
3309 Underflow = self.decimal.Underflow
3310 Clamped = self.decimal.Clamped
3311 Subnormal = self.decimal.Subnormal
3312 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
3313
3314 def raise_error(context, flag):
3315 if self.decimal == C:
3316 context.flags[flag] = True
3317 if context.traps[flag]:
3318 raise flag
3319 else:
3320 context._raise_error(flag)
3321
3322 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3323 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3324
3325 # operations that raise various flags, in the form (function, arglist)
3326 operations = [
3327 (context._apply, [Decimal("100E-425000010")]),
3328 (context.sqrt, [Decimal(2)]),
3329 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3330 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3331 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3332 ]
3333
3334 # try various flags individually, then a whole lot at once
3335 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3336 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3337
3338 for fn, args in operations:
3339 # find answer and flags raised using a clean context
3340 context.clear_flags()
3341 ans = fn(*args)
3342 flags = [k for k, v in context.flags.items() if v]
3343
3344 for extra_flags in flagsets:
3345 # set flags, before calling operation
3346 context.clear_flags()
3347 for flag in extra_flags:
3348 raise_error(context, flag)
3349 new_ans = fn(*args)
3350
3351 # flags that we expect to be set after the operation
3352 expected_flags = list(flags)
3353 for flag in extra_flags:
3354 if flag not in expected_flags:
3355 expected_flags.append(flag)
3356 expected_flags.sort(key=id)
3357
3358 # flags we actually got
3359 new_flags = [k for k,v in context.flags.items() if v]
3360 new_flags.sort(key=id)
3361
3362 self.assertEqual(ans, new_ans,
3363 "operation produces different answers depending on flags set: " +
3364 "expected %s, got %s." % (ans, new_ans))
3365 self.assertEqual(new_flags, expected_flags,
3366 "operation raises different flags depending on flags set: " +
3367 "expected %s, got %s" % (expected_flags, new_flags))
3368
3369 def test_flag_comparisons(self):
3370 Context = self.decimal.Context
3371 Inexact = self.decimal.Inexact
3372 Rounded = self.decimal.Rounded
3373
3374 c = Context()
3375
3376 # Valid SignalDict
3377 self.assertNotEqual(c.flags, c.traps)
3378 self.assertNotEqual(c.traps, c.flags)
3379
3380 c.flags = c.traps
3381 self.assertEqual(c.flags, c.traps)
3382 self.assertEqual(c.traps, c.flags)
3383
3384 c.flags[Rounded] = True
3385 c.traps = c.flags
3386 self.assertEqual(c.flags, c.traps)
3387 self.assertEqual(c.traps, c.flags)
3388
3389 d = {}
3390 d.update(c.flags)
3391 self.assertEqual(d, c.flags)
3392 self.assertEqual(c.flags, d)
3393
3394 d[Inexact] = True
3395 self.assertNotEqual(d, c.flags)
3396 self.assertNotEqual(c.flags, d)
3397
3398 # Invalid SignalDict
3399 d = {Inexact:False}
3400 self.assertNotEqual(d, c.flags)
3401 self.assertNotEqual(c.flags, d)
3402
3403 d = ["xyz"]
3404 self.assertNotEqual(d, c.flags)
3405 self.assertNotEqual(c.flags, d)
3406
3407 @requires_IEEE_754
3408 def test_float_operation(self):
3409 Decimal = self.decimal.Decimal
3410 FloatOperation = self.decimal.FloatOperation
3411 localcontext = self.decimal.localcontext
3412
3413 with localcontext() as c:
3414 ##### trap is off by default
3415 self.assertFalse(c.traps[FloatOperation])
3416
3417 # implicit conversion sets the flag
3418 c.clear_flags()
3419 self.assertEqual(Decimal(7.5), 7.5)
3420 self.assertTrue(c.flags[FloatOperation])
3421
3422 c.clear_flags()
3423 self.assertEqual(c.create_decimal(7.5), 7.5)
3424 self.assertTrue(c.flags[FloatOperation])
3425
3426 # explicit conversion does not set the flag
3427 c.clear_flags()
3428 x = Decimal.from_float(7.5)
3429 self.assertFalse(c.flags[FloatOperation])
3430 # comparison sets the flag
3431 self.assertEqual(x, 7.5)
3432 self.assertTrue(c.flags[FloatOperation])
3433
3434 c.clear_flags()
3435 x = c.create_decimal_from_float(7.5)
3436 self.assertFalse(c.flags[FloatOperation])
3437 self.assertEqual(x, 7.5)
3438 self.assertTrue(c.flags[FloatOperation])
3439
3440 ##### set the trap
3441 c.traps[FloatOperation] = True
3442
3443 # implicit conversion raises
3444 c.clear_flags()
3445 self.assertRaises(FloatOperation, Decimal, 7.5)
3446 self.assertTrue(c.flags[FloatOperation])
3447
3448 c.clear_flags()
3449 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3450 self.assertTrue(c.flags[FloatOperation])
3451
3452 # explicit conversion is silent
3453 c.clear_flags()
3454 x = Decimal.from_float(7.5)
3455 self.assertFalse(c.flags[FloatOperation])
3456
3457 c.clear_flags()
3458 x = c.create_decimal_from_float(7.5)
3459 self.assertFalse(c.flags[FloatOperation])
3460
3461 def test_float_comparison(self):
3462 Decimal = self.decimal.Decimal
3463 Context = self.decimal.Context
3464 FloatOperation = self.decimal.FloatOperation
3465 localcontext = self.decimal.localcontext
3466
3467 def assert_attr(a, b, attr, context, signal=None):
3468 context.clear_flags()
3469 f = getattr(a, attr)
3470 if signal == FloatOperation:
3471 self.assertRaises(signal, f, b)
3472 else:
3473 self.assertIs(f(b), True)
3474 self.assertTrue(context.flags[FloatOperation])
3475
3476 small_d = Decimal('0.25')
3477 big_d = Decimal('3.0')
3478 small_f = 0.25
3479 big_f = 3.0
3480
3481 zero_d = Decimal('0.0')
3482 neg_zero_d = Decimal('-0.0')
3483 zero_f = 0.0
3484 neg_zero_f = -0.0
3485
3486 inf_d = Decimal('Infinity')
3487 neg_inf_d = Decimal('-Infinity')
3488 inf_f = float('inf')
3489 neg_inf_f = float('-inf')
3490
3491 def doit(c, signal=None):
3492 # Order
3493 for attr in '__lt__', '__le__':
3494 assert_attr(small_d, big_f, attr, c, signal)
3495
3496 for attr in '__gt__', '__ge__':
3497 assert_attr(big_d, small_f, attr, c, signal)
3498
3499 # Equality
3500 assert_attr(small_d, small_f, '__eq__', c, None)
3501
3502 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3503 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3504
3505 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3506 assert_attr(zero_d, zero_f, '__eq__', c, None)
3507
3508 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3509 assert_attr(inf_d, inf_f, '__eq__', c, None)
3510
3511 # Inequality
3512 assert_attr(small_d, big_f, '__ne__', c, None)
3513
3514 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3515
3516 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3517 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3518
3519 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3520
3521 def test_containers(c, signal=None):
3522 c.clear_flags()
3523 s = set([100.0, Decimal('100.0')])
3524 self.assertEqual(len(s), 1)
3525 self.assertTrue(c.flags[FloatOperation])
3526
3527 c.clear_flags()
3528 if signal:
3529 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3530 else:
3531 s = sorted([10.0, Decimal('10.0')])
3532 self.assertTrue(c.flags[FloatOperation])
3533
3534 c.clear_flags()
3535 b = 10.0 in [Decimal('10.0'), 1.0]
3536 self.assertTrue(c.flags[FloatOperation])
3537
3538 c.clear_flags()
3539 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3540 self.assertTrue(c.flags[FloatOperation])
3541
3542 nc = Context()
3543 with localcontext(nc) as c:
3544 self.assertFalse(c.traps[FloatOperation])
3545 doit(c, signal=None)
3546 test_containers(c, signal=None)
3547
3548 c.traps[FloatOperation] = True
3549 doit(c, signal=FloatOperation)
3550 test_containers(c, signal=FloatOperation)
3551
3552 def test_float_operation_default(self):
3553 Decimal = self.decimal.Decimal
3554 Context = self.decimal.Context
3555 Inexact = self.decimal.Inexact
3556 FloatOperation= self.decimal.FloatOperation
3557
3558 context = Context()
3559 self.assertFalse(context.flags[FloatOperation])
3560 self.assertFalse(context.traps[FloatOperation])
3561
3562 context.clear_traps()
3563 context.traps[Inexact] = True
3564 context.traps[FloatOperation] = True
3565 self.assertTrue(context.traps[FloatOperation])
3566 self.assertTrue(context.traps[Inexact])
3567
3568class CContextFlags(ContextFlags):
3569 decimal = C
3570class PyContextFlags(ContextFlags):
3571 decimal = P
3572
3573class SpecialContexts(unittest.TestCase):
3574 """Test the context templates."""
3575
3576 def test_context_templates(self):
3577 BasicContext = self.decimal.BasicContext
3578 ExtendedContext = self.decimal.ExtendedContext
3579 getcontext = self.decimal.getcontext
3580 setcontext = self.decimal.setcontext
3581 InvalidOperation = self.decimal.InvalidOperation
3582 DivisionByZero = self.decimal.DivisionByZero
3583 Overflow = self.decimal.Overflow
3584 Underflow = self.decimal.Underflow
3585 Clamped = self.decimal.Clamped
3586
3587 assert_signals(self, BasicContext, 'traps',
3588 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3589 )
3590
3591 savecontext = getcontext().copy()
3592 basic_context_prec = BasicContext.prec
3593 extended_context_prec = ExtendedContext.prec
3594
3595 ex = None
3596 try:
3597 BasicContext.prec = ExtendedContext.prec = 441
3598 for template in BasicContext, ExtendedContext:
3599 setcontext(template)
3600 c = getcontext()
3601 self.assertIsNot(c, template)
3602 self.assertEqual(c.prec, 441)
3603 except Exception as e:
3604 ex = e.__class__
3605 finally:
3606 BasicContext.prec = basic_context_prec
3607 ExtendedContext.prec = extended_context_prec
3608 setcontext(savecontext)
3609 if ex:
3610 raise ex
3611
3612 def test_default_context(self):
3613 DefaultContext = self.decimal.DefaultContext
3614 BasicContext = self.decimal.BasicContext
3615 ExtendedContext = self.decimal.ExtendedContext
3616 getcontext = self.decimal.getcontext
3617 setcontext = self.decimal.setcontext
3618 InvalidOperation = self.decimal.InvalidOperation
3619 DivisionByZero = self.decimal.DivisionByZero
3620 Overflow = self.decimal.Overflow
3621
3622 self.assertEqual(BasicContext.prec, 9)
3623 self.assertEqual(ExtendedContext.prec, 9)
3624
3625 assert_signals(self, DefaultContext, 'traps',
3626 [InvalidOperation, DivisionByZero, Overflow]
3627 )
3628
3629 savecontext = getcontext().copy()
3630 default_context_prec = DefaultContext.prec
3631
3632 ex = None
3633 try:
3634 c = getcontext()
3635 saveprec = c.prec
3636
3637 DefaultContext.prec = 961
3638 c = getcontext()
3639 self.assertEqual(c.prec, saveprec)
3640
3641 setcontext(DefaultContext)
3642 c = getcontext()
3643 self.assertIsNot(c, DefaultContext)
3644 self.assertEqual(c.prec, 961)
3645 except Exception as e:
3646 ex = e.__class__
3647 finally:
3648 DefaultContext.prec = default_context_prec
3649 setcontext(savecontext)
3650 if ex:
3651 raise ex
3652
3653class CSpecialContexts(SpecialContexts):
3654 decimal = C
3655class PySpecialContexts(SpecialContexts):
3656 decimal = P
3657
3658class ContextInputValidation(unittest.TestCase):
3659
3660 def test_invalid_context(self):
3661 Context = self.decimal.Context
3662 DefaultContext = self.decimal.DefaultContext
3663
3664 c = DefaultContext.copy()
3665
3666 # prec, Emax
3667 for attr in ['prec', 'Emax']:
3668 setattr(c, attr, 999999)
3669 self.assertEqual(getattr(c, attr), 999999)
3670 self.assertRaises(ValueError, setattr, c, attr, -1)
3671 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3672
3673 # Emin
3674 setattr(c, 'Emin', -999999)
3675 self.assertEqual(getattr(c, 'Emin'), -999999)
3676 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3677 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3678
3679 # rounding: always raise TypeError in order to get consistent
3680 # exceptions across implementations. In decimal, rounding
3681 # modes are strings, in _decimal they are integers. The idea
3682 # is to view rounding as an abstract type and not mind the
3683 # implementation details.
3684 # Hence, a user should view the rounding modes as if they
3685 # had been defined in a language that supports abstract
3686 # data types, e.g. ocaml:
3687 #
3688 # type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;;
3689 #
3690 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3691 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3692 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3693 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3694
3695 # capitals, clamp
3696 for attr in ['capitals', 'clamp']:
3697 self.assertRaises(ValueError, setattr, c, attr, -1)
3698 self.assertRaises(ValueError, setattr, c, attr, 2)
3699 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3700
3701 # Invalid attribute
3702 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3703
3704 # Invalid signal dict
3705 self.assertRaises(TypeError, setattr, c, 'flags', [])
3706 self.assertRaises(KeyError, setattr, c, 'flags', {})
3707 self.assertRaises(KeyError, setattr, c, 'traps',
3708 {'InvalidOperation':0})
3709
3710 # Attributes cannot be deleted
3711 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3712 'flags', 'traps']:
3713 self.assertRaises(AttributeError, c.__delattr__, attr)
3714
3715 # Invalid attributes
3716 self.assertRaises(TypeError, getattr, c, 9)
3717 self.assertRaises(TypeError, setattr, c, 9)
3718
3719 # Invalid values in constructor
3720 self.assertRaises(TypeError, Context, rounding=999999)
3721 self.assertRaises(TypeError, Context, rounding='xyz')
3722 self.assertRaises(ValueError, Context, clamp=2)
3723 self.assertRaises(ValueError, Context, capitals=-1)
3724 self.assertRaises(KeyError, Context, flags=["P"])
3725 self.assertRaises(KeyError, Context, traps=["Q"])
3726
3727 # Type error in conversion
3728 self.assertRaises(TypeError, Context, flags=(0,1))
3729 self.assertRaises(TypeError, Context, traps=(1,0))
3730
3731class CContextInputValidation(ContextInputValidation):
3732 decimal = C
3733class PyContextInputValidation(ContextInputValidation):
3734 decimal = P
3735
3736class ContextSubclassing(unittest.TestCase):
3737
3738 def test_context_subclassing(self):
3739 decimal = self.decimal
3740 Decimal = decimal.Decimal
3741 Context = decimal.Context
3742 ROUND_HALF_EVEN = decimal.ROUND_HALF_EVEN
3743 ROUND_DOWN = decimal.ROUND_DOWN
3744 Clamped = decimal.Clamped
3745 DivisionByZero = decimal.DivisionByZero
3746 Inexact = decimal.Inexact
3747 Overflow = decimal.Overflow
3748 Rounded = decimal.Rounded
3749 Subnormal = decimal.Subnormal
3750 Underflow = decimal.Underflow
3751 InvalidOperation = decimal.InvalidOperation
3752
3753 class MyContext(Context):
3754 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
3755 capitals=None, clamp=None, flags=None,
3756 traps=None):
3757 Context.__init__(self)
3758 if prec is not None:
3759 self.prec = prec
3760 if rounding is not None:
3761 self.rounding = rounding
3762 if Emin is not None:
3763 self.Emin = Emin
3764 if Emax is not None:
3765 self.Emax = Emax
3766 if capitals is not None:
3767 self.capitals = capitals
3768 if clamp is not None:
3769 self.clamp = clamp
3770 if flags is not None:
3771 if isinstance(flags, list):
3772 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
3773 self.flags = flags
3774 if traps is not None:
3775 if isinstance(traps, list):
3776 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
3777 self.traps = traps
3778
3779 c = Context()
3780 d = MyContext()
3781 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
3782 'flags', 'traps'):
3783 self.assertEqual(getattr(c, attr), getattr(d, attr))
3784
3785 # prec
3786 self.assertRaises(ValueError, MyContext, **{'prec':-1})
3787 c = MyContext(prec=1)
3788 self.assertEqual(c.prec, 1)
3789 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
3790
3791 # rounding
3792 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
3793 c = MyContext(rounding=ROUND_DOWN, prec=1)
3794 self.assertEqual(c.rounding, ROUND_DOWN)
3795 self.assertEqual(c.plus(Decimal('9.9')), 9)
3796
3797 # Emin
3798 self.assertRaises(ValueError, MyContext, **{'Emin':5})
3799 c = MyContext(Emin=-1, prec=1)
3800 self.assertEqual(c.Emin, -1)
3801 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
3802 self.assertEqual(x, Decimal('0.0'))
3803 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
3804 self.assertTrue(c.flags[signal])
3805
3806 # Emax
3807 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
3808 c = MyContext(Emax=1, prec=1)
3809 self.assertEqual(c.Emax, 1)
3810 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
3811 if self.decimal == C:
3812 for signal in (Inexact, Overflow, Rounded):
3813 self.assertTrue(c.flags[signal])
3814
3815 # capitals
3816 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
3817 c = MyContext(capitals=0)
3818 self.assertEqual(c.capitals, 0)
3819 x = c.create_decimal('1E222')
3820 self.assertEqual(c.to_sci_string(x), '1e+222')
3821
3822 # clamp
3823 self.assertRaises(ValueError, MyContext, **{'clamp':2})
3824 c = MyContext(clamp=1, Emax=99)
3825 self.assertEqual(c.clamp, 1)
3826 x = c.plus(Decimal('1e99'))
3827 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
3828
3829 # flags
3830 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
3831 c = MyContext(flags=[Rounded, DivisionByZero])
3832 for signal in (Rounded, DivisionByZero):
3833 self.assertTrue(c.flags[signal])
3834 c.clear_flags()
3835 for signal in OrderedSignals[decimal]:
3836 self.assertFalse(c.flags[signal])
3837
3838 # traps
3839 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
3840 c = MyContext(traps=[Rounded, DivisionByZero])
3841 for signal in (Rounded, DivisionByZero):
3842 self.assertTrue(c.traps[signal])
3843 c.clear_traps()
3844 for signal in OrderedSignals[decimal]:
3845 self.assertFalse(c.traps[signal])
3846
3847class CContextSubclassing(ContextSubclassing):
3848 decimal = C
3849class PyContextSubclassing(ContextSubclassing):
3850 decimal = P
3851
3852@skip_if_extra_functionality
3853class CheckAttributes(unittest.TestCase):
3854
3855 def test_module_attributes(self):
3856
3857 # Architecture dependent context limits
3858 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
3859 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
3860 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
3861 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
3862
3863 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
3864 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
3865
3866 self.assertEqual(C.__version__, P.__version__)
3867
3868 x = dir(C)
3869 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02003870 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01003871
3872 def test_context_attributes(self):
3873
3874 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
3875 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
3876 self.assertEqual(set(x) - set(y), set())
3877
3878 def test_decimal_attributes(self):
3879
3880 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3881 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3882 self.assertEqual(set(x) - set(y), set())
3883
3884class Coverage(unittest.TestCase):
3885
3886 def test_adjusted(self):
3887 Decimal = self.decimal.Decimal
3888
3889 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
3890 # XXX raise?
3891 self.assertEqual(Decimal('nan').adjusted(), 0)
3892 self.assertEqual(Decimal('inf').adjusted(), 0)
3893
3894 def test_canonical(self):
3895 Decimal = self.decimal.Decimal
3896 getcontext = self.decimal.getcontext
3897
3898 x = Decimal(9).canonical()
3899 self.assertEqual(x, 9)
3900
3901 c = getcontext()
3902 x = c.canonical(Decimal(9))
3903 self.assertEqual(x, 9)
3904
3905 def test_context_repr(self):
3906 c = self.decimal.DefaultContext.copy()
3907
3908 c.prec = 425000000
3909 c.Emax = 425000000
3910 c.Emin = -425000000
3911 c.rounding = self.decimal.ROUND_HALF_DOWN
3912 c.capitals = 0
3913 c.clamp = 1
3914 for sig in OrderedSignals[self.decimal]:
3915 c.flags[sig] = False
3916 c.traps[sig] = False
3917
3918 s = c.__repr__()
3919 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
3920 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
3921 "flags=[], traps=[])"
3922 self.assertEqual(s, t)
3923
3924 def test_implicit_context(self):
3925 Decimal = self.decimal.Decimal
3926 localcontext = self.decimal.localcontext
3927
3928 with localcontext() as c:
3929 c.prec = 1
3930 c.Emax = 1
3931 c.Emin = -1
3932
3933 # abs
3934 self.assertEqual(abs(Decimal("-10")), 10)
3935 # add
3936 self.assertEqual(Decimal("7") + 1, 8)
3937 # divide
3938 self.assertEqual(Decimal("10") / 5, 2)
3939 # divide_int
3940 self.assertEqual(Decimal("10") // 7, 1)
3941 # fma
3942 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
3943 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
3944 # three arg power
3945 self.assertEqual(pow(Decimal(10), 2, 7), 2)
3946 # exp
3947 self.assertEqual(Decimal("1.01").exp(), 3)
3948 # is_normal
3949 self.assertIs(Decimal("0.01").is_normal(), False)
3950 # is_subnormal
3951 self.assertIs(Decimal("0.01").is_subnormal(), True)
3952 # ln
3953 self.assertEqual(Decimal("20").ln(), 3)
3954 # log10
3955 self.assertEqual(Decimal("20").log10(), 1)
3956 # logb
3957 self.assertEqual(Decimal("580").logb(), 2)
3958 # logical_invert
3959 self.assertEqual(Decimal("10").logical_invert(), 1)
3960 # minus
3961 self.assertEqual(-Decimal("-10"), 10)
3962 # multiply
3963 self.assertEqual(Decimal("2") * 4, 8)
3964 # next_minus
3965 self.assertEqual(Decimal("10").next_minus(), 9)
3966 # next_plus
3967 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
3968 # normalize
3969 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
3970 # number_class
3971 self.assertEqual(Decimal("10").number_class(), '+Normal')
3972 # plus
3973 self.assertEqual(+Decimal("-1"), -1)
3974 # remainder
3975 self.assertEqual(Decimal("10") % 7, 3)
3976 # subtract
3977 self.assertEqual(Decimal("10") - 7, 3)
3978 # to_integral_exact
3979 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
3980
3981 # Boolean functions
3982 self.assertTrue(Decimal("1").is_canonical())
3983 self.assertTrue(Decimal("1").is_finite())
3984 self.assertTrue(Decimal("1").is_finite())
3985 self.assertTrue(Decimal("snan").is_snan())
3986 self.assertTrue(Decimal("-1").is_signed())
3987 self.assertTrue(Decimal("0").is_zero())
3988 self.assertTrue(Decimal("0").is_zero())
3989
3990 # Copy
3991 with localcontext() as c:
3992 c.prec = 10000
3993 x = 1228 ** 1523
3994 y = -Decimal(x)
3995
3996 z = y.copy_abs()
3997 self.assertEqual(z, x)
3998
3999 z = y.copy_negate()
4000 self.assertEqual(z, x)
4001
4002 z = y.copy_sign(Decimal(1))
4003 self.assertEqual(z, x)
4004
4005 def test_divmod(self):
4006 Decimal = self.decimal.Decimal
4007 localcontext = self.decimal.localcontext
4008 InvalidOperation = self.decimal.InvalidOperation
4009 DivisionByZero = self.decimal.DivisionByZero
4010
4011 with localcontext() as c:
4012 q, r = divmod(Decimal("10912837129"), 1001)
4013 self.assertEqual(q, Decimal('10901935'))
4014 self.assertEqual(r, Decimal('194'))
4015
4016 q, r = divmod(Decimal("NaN"), 7)
4017 self.assertTrue(q.is_nan() and r.is_nan())
4018
4019 c.traps[InvalidOperation] = False
4020 q, r = divmod(Decimal("NaN"), 7)
4021 self.assertTrue(q.is_nan() and r.is_nan())
4022
4023 c.traps[InvalidOperation] = False
4024 c.clear_flags()
4025 q, r = divmod(Decimal("inf"), Decimal("inf"))
4026 self.assertTrue(q.is_nan() and r.is_nan())
4027 self.assertTrue(c.flags[InvalidOperation])
4028
4029 c.clear_flags()
4030 q, r = divmod(Decimal("inf"), 101)
4031 self.assertTrue(q.is_infinite() and r.is_nan())
4032 self.assertTrue(c.flags[InvalidOperation])
4033
4034 c.clear_flags()
4035 q, r = divmod(Decimal(0), 0)
4036 self.assertTrue(q.is_nan() and r.is_nan())
4037 self.assertTrue(c.flags[InvalidOperation])
4038
4039 c.traps[DivisionByZero] = False
4040 c.clear_flags()
4041 q, r = divmod(Decimal(11), 0)
4042 self.assertTrue(q.is_infinite() and r.is_nan())
4043 self.assertTrue(c.flags[InvalidOperation] and
4044 c.flags[DivisionByZero])
4045
4046 def test_power(self):
4047 Decimal = self.decimal.Decimal
4048 localcontext = self.decimal.localcontext
4049 Overflow = self.decimal.Overflow
4050 Rounded = self.decimal.Rounded
4051
4052 with localcontext() as c:
4053 c.prec = 3
4054 c.clear_flags()
4055 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4056 self.assertTrue(c.flags[Rounded])
4057
4058 c.prec = 1
4059 c.Emax = 1
4060 c.Emin = -1
4061 c.clear_flags()
4062 c.traps[Overflow] = False
4063 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4064 self.assertTrue(c.flags[Overflow])
4065
4066 def test_quantize(self):
4067 Decimal = self.decimal.Decimal
4068 localcontext = self.decimal.localcontext
4069 InvalidOperation = self.decimal.InvalidOperation
4070
4071 with localcontext() as c:
4072 c.prec = 1
4073 c.Emax = 1
4074 c.Emin = -1
4075 c.traps[InvalidOperation] = False
4076 x = Decimal(99).quantize(Decimal("1e1"))
4077 self.assertTrue(x.is_nan())
4078
4079 def test_radix(self):
4080 Decimal = self.decimal.Decimal
4081 getcontext = self.decimal.getcontext
4082
4083 c = getcontext()
4084 self.assertEqual(Decimal("1").radix(), 10)
4085 self.assertEqual(c.radix(), 10)
4086
4087 def test_rop(self):
4088 Decimal = self.decimal.Decimal
4089
4090 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4091 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4092 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4093
4094 def test_round(self):
4095 # Python3 behavior: round() returns Decimal
4096 Decimal = self.decimal.Decimal
4097 getcontext = self.decimal.getcontext
4098
4099 c = getcontext()
4100 c.prec = 28
4101
4102 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4103 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4104 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4105 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4106 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4107
4108 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4109 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4110
4111 def test_create_decimal(self):
4112 c = self.decimal.Context()
4113 self.assertRaises(ValueError, c.create_decimal, ["%"])
4114
4115 def test_int(self):
4116 Decimal = self.decimal.Decimal
4117 localcontext = self.decimal.localcontext
4118
4119 with localcontext() as c:
4120 c.prec = 9999
4121 x = Decimal(1221**1271) / 10**3923
4122 self.assertEqual(int(x), 1)
4123 self.assertEqual(x.to_integral(), 2)
4124
4125 def test_copy(self):
4126 Context = self.decimal.Context
4127
4128 c = Context()
4129 c.prec = 10000
4130 x = -(1172 ** 1712)
4131
4132 y = c.copy_abs(x)
4133 self.assertEqual(y, -x)
4134
4135 y = c.copy_negate(x)
4136 self.assertEqual(y, -x)
4137
4138 y = c.copy_sign(x, 1)
4139 self.assertEqual(y, -x)
4140
4141class CCoverage(Coverage):
4142 decimal = C
4143class PyCoverage(Coverage):
4144 decimal = P
4145
4146class PyFunctionality(unittest.TestCase):
4147 """Extra functionality in decimal.py"""
4148
4149 def test_py_quantize_watchexp(self):
4150 # watchexp functionality
4151 Decimal = P.Decimal
4152 localcontext = P.localcontext
4153
4154 with localcontext() as c:
4155 c.prec = 1
4156 c.Emax = 1
4157 c.Emin = -1
4158 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4159 self.assertEqual(x, Decimal('1.00E+5'))
4160
4161 def test_py_alternate_formatting(self):
4162 # triples giving a format, a Decimal, and the expected result
4163 Decimal = P.Decimal
4164 localcontext = P.localcontext
4165
4166 test_values = [
4167 # Issue 7094: Alternate formatting (specified by #)
4168 ('.0e', '1.0', '1e+0'),
4169 ('#.0e', '1.0', '1.e+0'),
4170 ('.0f', '1.0', '1'),
4171 ('#.0f', '1.0', '1.'),
4172 ('g', '1.1', '1.1'),
4173 ('#g', '1.1', '1.1'),
4174 ('.0g', '1', '1'),
4175 ('#.0g', '1', '1.'),
4176 ('.0%', '1.0', '100%'),
4177 ('#.0%', '1.0', '100.%'),
4178 ]
4179 for fmt, d, result in test_values:
4180 self.assertEqual(format(Decimal(d), fmt), result)
4181
4182class PyWhitebox(unittest.TestCase):
4183 """White box testing for decimal.py"""
4184
4185 def test_py_exact_power(self):
4186 # Rarely exercised lines in _power_exact.
4187 Decimal = P.Decimal
4188 localcontext = P.localcontext
4189
4190 with localcontext() as c:
4191 c.prec = 8
4192 x = Decimal(2**16) ** Decimal("-0.5")
4193 self.assertEqual(x, Decimal('0.00390625'))
4194
4195 x = Decimal(2**16) ** Decimal("-0.6")
4196 self.assertEqual(x, Decimal('0.0012885819'))
4197
4198 x = Decimal("256e7") ** Decimal("-0.5")
4199
4200 x = Decimal(152587890625) ** Decimal('-0.0625')
4201 self.assertEqual(x, Decimal("0.2"))
4202
4203 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4204
4205 x = Decimal(5**2659) ** Decimal('-0.0625')
4206
4207 c.prec = 1
4208 x = Decimal("152587890625") ** Decimal('-0.5')
4209 c.prec = 201
4210 x = Decimal(2**578) ** Decimal("-0.5")
4211
4212 def test_py_immutability_operations(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004213 # Do operations and check that it didn't change change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004214 Decimal = P.Decimal
4215 DefaultContext = P.DefaultContext
4216 setcontext = P.setcontext
4217
4218 c = DefaultContext.copy()
4219 c.traps = dict((s, 0) for s in OrderedSignals[P])
4220 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004221
4222 d1 = Decimal('-25e55')
4223 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004224 d2 = Decimal('33e+33')
4225 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004226
4227 def checkSameDec(operation, useOther=False):
4228 if useOther:
4229 eval("d1." + operation + "(d2)")
4230 self.assertEqual(d1._sign, b1._sign)
4231 self.assertEqual(d1._int, b1._int)
4232 self.assertEqual(d1._exp, b1._exp)
4233 self.assertEqual(d2._sign, b2._sign)
4234 self.assertEqual(d2._int, b2._int)
4235 self.assertEqual(d2._exp, b2._exp)
4236 else:
4237 eval("d1." + operation + "()")
4238 self.assertEqual(d1._sign, b1._sign)
4239 self.assertEqual(d1._int, b1._int)
4240 self.assertEqual(d1._exp, b1._exp)
4241 return
4242
4243 Decimal(d1)
4244 self.assertEqual(d1._sign, b1._sign)
4245 self.assertEqual(d1._int, b1._int)
4246 self.assertEqual(d1._exp, b1._exp)
4247
4248 checkSameDec("__abs__")
4249 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004250 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004251 checkSameDec("__eq__", True)
4252 checkSameDec("__ne__", True)
4253 checkSameDec("__le__", True)
4254 checkSameDec("__lt__", True)
4255 checkSameDec("__ge__", True)
4256 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004257 checkSameDec("__float__")
4258 checkSameDec("__floordiv__", True)
4259 checkSameDec("__hash__")
4260 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004261 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004262 checkSameDec("__mod__", True)
4263 checkSameDec("__mul__", True)
4264 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004265 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004266 checkSameDec("__pos__")
4267 checkSameDec("__pow__", True)
4268 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004269 checkSameDec("__rdivmod__", True)
4270 checkSameDec("__repr__")
4271 checkSameDec("__rfloordiv__", True)
4272 checkSameDec("__rmod__", True)
4273 checkSameDec("__rmul__", True)
4274 checkSameDec("__rpow__", True)
4275 checkSameDec("__rsub__", True)
4276 checkSameDec("__str__")
4277 checkSameDec("__sub__", True)
4278 checkSameDec("__truediv__", True)
4279 checkSameDec("adjusted")
4280 checkSameDec("as_tuple")
4281 checkSameDec("compare", True)
4282 checkSameDec("max", True)
4283 checkSameDec("min", True)
4284 checkSameDec("normalize")
4285 checkSameDec("quantize", True)
4286 checkSameDec("remainder_near", True)
4287 checkSameDec("same_quantum", True)
4288 checkSameDec("sqrt")
4289 checkSameDec("to_eng_string")
4290 checkSameDec("to_integral")
4291
Stefan Krah1919b7e2012-03-21 18:25:23 +01004292 def test_py_decimal_id(self):
4293 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004294
Stefan Krah1919b7e2012-03-21 18:25:23 +01004295 d = Decimal(45)
4296 e = Decimal(d)
4297 self.assertEqual(str(e), '45')
4298 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004299
Stefan Krah1919b7e2012-03-21 18:25:23 +01004300 def test_py_rescale(self):
4301 # Coverage
4302 Decimal = P.Decimal
4303 ROUND_UP = P.ROUND_UP
4304 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004305
Stefan Krah1919b7e2012-03-21 18:25:23 +01004306 with localcontext() as c:
4307 x = Decimal("NaN")._rescale(3, ROUND_UP)
4308 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004309
Stefan Krah1919b7e2012-03-21 18:25:23 +01004310 def test_py__round(self):
4311 # Coverage
4312 Decimal = P.Decimal
4313 ROUND_UP = P.ROUND_UP
Christian Heimes0348fb62008-03-26 12:55:56 +00004314
Stefan Krah1919b7e2012-03-21 18:25:23 +01004315 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004316
Stefan Krah1919b7e2012-03-21 18:25:23 +01004317class CFunctionality(unittest.TestCase):
4318 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004319
Stefan Krah1919b7e2012-03-21 18:25:23 +01004320 @requires_extra_functionality
4321 def test_c_ieee_context(self):
4322 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4323 IEEEContext = C.IEEEContext
4324 DECIMAL32 = C.DECIMAL32
4325 DECIMAL64 = C.DECIMAL64
4326 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004327
Stefan Krah1919b7e2012-03-21 18:25:23 +01004328 def assert_rest(self, context):
4329 self.assertEqual(context.clamp, 1)
4330 assert_signals(self, context, 'traps', [])
4331 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004332
Stefan Krah1919b7e2012-03-21 18:25:23 +01004333 c = IEEEContext(DECIMAL32)
4334 self.assertEqual(c.prec, 7)
4335 self.assertEqual(c.Emax, 96)
4336 self.assertEqual(c.Emin, -95)
4337 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004338
Stefan Krah1919b7e2012-03-21 18:25:23 +01004339 c = IEEEContext(DECIMAL64)
4340 self.assertEqual(c.prec, 16)
4341 self.assertEqual(c.Emax, 384)
4342 self.assertEqual(c.Emin, -383)
4343 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004344
Stefan Krah1919b7e2012-03-21 18:25:23 +01004345 c = IEEEContext(DECIMAL128)
4346 self.assertEqual(c.prec, 34)
4347 self.assertEqual(c.Emax, 6144)
4348 self.assertEqual(c.Emin, -6143)
4349 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004350
Stefan Krah1919b7e2012-03-21 18:25:23 +01004351 # Invalid values
4352 self.assertRaises(OverflowError, IEEEContext, 2**63)
4353 self.assertRaises(ValueError, IEEEContext, -1)
4354 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004355
Stefan Krah1919b7e2012-03-21 18:25:23 +01004356 @requires_extra_functionality
4357 def test_c_context(self):
4358 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004359
Stefan Krah1919b7e2012-03-21 18:25:23 +01004360 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4361 self.assertEqual(c._flags, C.DecClamped)
4362 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004363
Stefan Krah1919b7e2012-03-21 18:25:23 +01004364 @requires_extra_functionality
4365 def test_constants(self):
4366 # Condition flags
4367 cond = (
4368 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4369 C.DecDivisionImpossible, C.DecDivisionUndefined,
4370 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4371 C.DecInvalidOperation, C.DecMallocError,
4372 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4373 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004374 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004375
4376 # IEEEContext
4377 self.assertEqual(C.DECIMAL32, 32)
4378 self.assertEqual(C.DECIMAL64, 64)
4379 self.assertEqual(C.DECIMAL128, 128)
4380 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4381
4382 # Rounding modes
4383 for i, v in enumerate(RoundingModes[C]):
4384 self.assertEqual(v, i)
4385 self.assertEqual(C.ROUND_TRUNC, 8)
4386
4387 # Conditions
4388 for i, v in enumerate(cond):
4389 self.assertEqual(v, 1<<i)
4390
4391 self.assertEqual(C.DecIEEEInvalidOperation,
4392 C.DecConversionSyntax|
4393 C.DecDivisionImpossible|
4394 C.DecDivisionUndefined|
4395 C.DecFpuError|
4396 C.DecInvalidContext|
4397 C.DecInvalidOperation|
4398 C.DecMallocError)
4399
4400 self.assertEqual(C.DecErrors,
4401 C.DecIEEEInvalidOperation|
4402 C.DecDivisionByZero)
4403
4404 self.assertEqual(C.DecTraps,
4405 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4406
4407class CWhitebox(unittest.TestCase):
4408 """Whitebox testing for _decimal"""
4409
4410 def test_bignum(self):
4411 # Not exactly whitebox, but too slow with pydecimal.
4412
4413 Decimal = C.Decimal
4414 localcontext = C.localcontext
4415
4416 b1 = 10**35
4417 b2 = 10**36
4418 with localcontext() as c:
4419 c.prec = 1000000
4420 for i in range(5):
4421 a = random.randrange(b1, b2)
4422 b = random.randrange(1000, 1200)
4423 x = a ** b
4424 y = Decimal(a) ** Decimal(b)
4425 self.assertEqual(x, y)
4426
4427 def test_invalid_construction(self):
4428 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4429
4430 def test_c_input_restriction(self):
4431 # Too large for _decimal to be converted exactly
4432 Decimal = C.Decimal
4433 InvalidOperation = C.InvalidOperation
4434 Context = C.Context
4435 localcontext = C.localcontext
4436
4437 with localcontext(Context()):
4438 self.assertRaises(InvalidOperation, Decimal,
4439 "1e9999999999999999999")
4440
4441 def test_c_context_repr(self):
4442 # This test is _decimal-only because flags are not printed
4443 # in the same order.
4444 DefaultContext = C.DefaultContext
4445 FloatOperation = C.FloatOperation
4446 ROUND_HALF_DOWN = C.ROUND_HALF_DOWN
4447
4448 c = DefaultContext.copy()
4449
4450 c.prec = 425000000
4451 c.Emax = 425000000
4452 c.Emin = -425000000
4453 c.rounding = ROUND_HALF_DOWN
4454 c.capitals = 0
4455 c.clamp = 1
4456 for sig in OrderedSignals[C]:
4457 c.flags[sig] = True
4458 c.traps[sig] = True
4459 c.flags[FloatOperation] = True
4460 c.traps[FloatOperation] = True
4461
4462 s = c.__repr__()
4463 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4464 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4465 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4466 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4467 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4468 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4469 self.assertEqual(s, t)
4470
4471 def test_c_context_errors(self):
4472 Context = C.Context
4473 InvalidOperation = C.InvalidOperation
4474 Overflow = C.Overflow
4475 FloatOperation = C.FloatOperation
4476 localcontext = C.localcontext
4477 getcontext = C.getcontext
4478 setcontext = C.setcontext
4479 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4480
4481 c = Context()
4482
4483 # SignalDict: input validation
4484 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4485 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4486 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4487 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4488 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4489 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4490 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4491 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4492
4493 # Test assignment from a signal dict with the correct length but
4494 # one invalid key.
4495 d = c.flags.copy()
4496 del d[FloatOperation]
4497 d["XYZ"] = 91283719
4498 self.assertRaises(KeyError, setattr, c, 'flags', d)
4499 self.assertRaises(KeyError, setattr, c, 'traps', d)
4500
4501 # Input corner cases
4502 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4503 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4504
4505 # prec, Emax, Emin
4506 for attr in ['prec', 'Emax']:
4507 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4508 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4509
4510 # prec, Emax, Emin in context constructor
4511 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4512 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4513 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4514
4515 # Overflow in conversion
4516 self.assertRaises(OverflowError, Context, prec=int_max+1)
4517 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4518 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
4519 self.assertRaises(OverflowError, Context, rounding=int_max+1)
4520 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4521 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4522
4523 # OverflowError, general ValueError
4524 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4525 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4526 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4527 if sys.platform != 'win32':
4528 self.assertRaises(ValueError, setattr, c, attr, int_max)
4529 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4530
4531 # OverflowError, general TypeError
4532 for attr in ('rounding',):
4533 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4534 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4535 if sys.platform != 'win32':
4536 self.assertRaises(TypeError, setattr, c, attr, int_max)
4537 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4538
4539 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4540 if C.MAX_PREC == 425000000:
4541 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4542 int_max+1)
4543 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4544 int_max+1)
4545 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4546 -int_max-2)
4547
4548 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4549 if C.MAX_PREC == 425000000:
4550 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4551 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4552 1070000001)
4553 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4554 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4555 1070000001)
4556 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4557 -1070000001)
4558 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4559
4560 # capitals, clamp
4561 for attr in ['capitals', 'clamp']:
4562 self.assertRaises(ValueError, setattr, c, attr, -1)
4563 self.assertRaises(ValueError, setattr, c, attr, 2)
4564 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4565 if HAVE_CONFIG_64:
4566 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4567 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4568
4569 # Invalid local context
4570 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4571 locals())
4572
4573 # setcontext
4574 saved_context = getcontext()
4575 self.assertRaises(TypeError, setcontext, "xyz")
4576 setcontext(saved_context)
4577
4578 @requires_extra_functionality
4579 def test_c_context_errors_extra(self):
4580 Context = C.Context
4581 InvalidOperation = C.InvalidOperation
4582 Overflow = C.Overflow
4583 localcontext = C.localcontext
4584 getcontext = C.getcontext
4585 setcontext = C.setcontext
4586 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4587
4588 c = Context()
4589
4590 # Input corner cases
4591 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4592
4593 # OverflowError, general ValueError
4594 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4595 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4596 if sys.platform != 'win32':
4597 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4598 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4599
4600 # OverflowError, general TypeError
4601 for attr in ('_flags', '_traps'):
4602 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4603 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4604 if sys.platform != 'win32':
4605 self.assertRaises(TypeError, setattr, c, attr, int_max)
4606 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4607
4608 # _allcr
4609 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4610 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4611 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4612 if HAVE_CONFIG_64:
4613 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4614 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4615
4616 # _flags, _traps
4617 for attr in ['_flags', '_traps']:
4618 self.assertRaises(TypeError, setattr, c, attr, 999999)
4619 self.assertRaises(TypeError, setattr, c, attr, 'x')
4620
4621 def test_c_valid_context(self):
4622 # These tests are for code coverage in _decimal.
4623 DefaultContext = C.DefaultContext
4624 ROUND_HALF_UP = C.ROUND_HALF_UP
4625 Clamped = C.Clamped
4626 Underflow = C.Underflow
4627 Inexact = C.Inexact
4628 Rounded = C.Rounded
4629 Subnormal = C.Subnormal
4630
4631 c = DefaultContext.copy()
4632
4633 # Exercise all getters and setters
4634 c.prec = 34
4635 c.rounding = ROUND_HALF_UP
4636 c.Emax = 3000
4637 c.Emin = -3000
4638 c.capitals = 1
4639 c.clamp = 0
4640
4641 self.assertEqual(c.prec, 34)
4642 self.assertEqual(c.rounding, ROUND_HALF_UP)
4643 self.assertEqual(c.Emin, -3000)
4644 self.assertEqual(c.Emax, 3000)
4645 self.assertEqual(c.capitals, 1)
4646 self.assertEqual(c.clamp, 0)
4647
4648 self.assertEqual(c.Etiny(), -3033)
4649 self.assertEqual(c.Etop(), 2967)
4650
4651 # Exercise all unsafe setters
4652 if C.MAX_PREC == 425000000:
4653 c._unsafe_setprec(999999999)
4654 c._unsafe_setemax(999999999)
4655 c._unsafe_setemin(-999999999)
4656 self.assertEqual(c.prec, 999999999)
4657 self.assertEqual(c.Emax, 999999999)
4658 self.assertEqual(c.Emin, -999999999)
4659
4660 @requires_extra_functionality
4661 def test_c_valid_context_extra(self):
4662 DefaultContext = C.DefaultContext
4663
4664 c = DefaultContext.copy()
4665 self.assertEqual(c._allcr, 1)
4666 c._allcr = 0
4667 self.assertEqual(c._allcr, 0)
4668
4669 def test_c_round(self):
4670 # Restricted input.
4671 Decimal = C.Decimal
4672 InvalidOperation = C.InvalidOperation
4673 localcontext = C.localcontext
4674 MAX_EMAX = C.MAX_EMAX
4675 MIN_ETINY = C.MIN_ETINY
4676 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4677
4678 with localcontext() as c:
4679 c.traps[InvalidOperation] = True
4680 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4681 -int_max-1)
4682 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4683 int_max)
4684 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4685 int(MAX_EMAX+1))
4686 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4687 -int(MIN_ETINY-1))
4688 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4689 -int_max-2)
4690 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4691 int_max+1)
4692
4693 def test_c_format(self):
4694 # Restricted input
4695 Decimal = C.Decimal
4696 InvalidOperation = C.InvalidOperation
4697 Rounded = C.Rounded
4698 localcontext = C.localcontext
4699 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4700
4701 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4702 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4703 self.assertRaises(TypeError, Decimal(1).__format__, [])
4704
4705 with localcontext() as c:
4706 c.traps[InvalidOperation] = True
4707 c.traps[Rounded] = True
4708 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4709 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4710 self.assertRaises(InvalidOperation, Decimal("1.23456789").__format__,
4711 "=%d.1" % maxsize)
4712
4713 def test_c_integral(self):
4714 Decimal = C.Decimal
4715 Inexact = C.Inexact
4716 ROUND_UP = C.ROUND_UP
4717 localcontext = C.localcontext
4718
4719 x = Decimal(10)
4720 self.assertEqual(x.to_integral(), 10)
4721 self.assertRaises(TypeError, x.to_integral, '10')
4722 self.assertRaises(TypeError, x.to_integral, 10, 'x')
4723 self.assertRaises(TypeError, x.to_integral, 10)
4724
4725 self.assertEqual(x.to_integral_value(), 10)
4726 self.assertRaises(TypeError, x.to_integral_value, '10')
4727 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
4728 self.assertRaises(TypeError, x.to_integral_value, 10)
4729
4730 self.assertEqual(x.to_integral_exact(), 10)
4731 self.assertRaises(TypeError, x.to_integral_exact, '10')
4732 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
4733 self.assertRaises(TypeError, x.to_integral_exact, 10)
4734
4735 with localcontext() as c:
4736 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
4737 self.assertEqual(x, Decimal('100000000000000000000000000'))
4738
4739 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
4740 self.assertEqual(x, Decimal('100000000000000000000000000'))
4741
4742 c.traps[Inexact] = True
4743 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
4744
4745 def test_c_funcs(self):
4746 # Invalid arguments
4747 Decimal = C.Decimal
4748 InvalidOperation = C.InvalidOperation
4749 DivisionByZero = C.DivisionByZero
4750 ROUND_UP = C.ROUND_UP
4751 getcontext = C.getcontext
4752 localcontext = C.localcontext
4753
4754 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
4755
4756 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
4757 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
4758 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
4759
Raymond Hettinger771ed762009-01-03 19:20:32 +00004760 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01004761 TypeError,
4762 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00004763 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004764 self.assertRaises(
4765 TypeError,
4766 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
4767 )
4768 self.assertRaises(
4769 TypeError,
4770 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
4771 )
4772 self.assertRaises(
4773 TypeError,
4774 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
4775 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00004776
Stefan Krah1919b7e2012-03-21 18:25:23 +01004777 with localcontext() as c:
4778 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004779
Stefan Krah1919b7e2012-03-21 18:25:23 +01004780 # Invalid arguments
4781 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
4782 self.assertRaises(TypeError, c.canonical, 200)
4783 self.assertRaises(TypeError, c.is_canonical, 200)
4784 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
4785 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004786
Stefan Krah1919b7e2012-03-21 18:25:23 +01004787 self.assertEqual(str(c.canonical(Decimal(200))), '200')
4788 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00004789
Stefan Krah1919b7e2012-03-21 18:25:23 +01004790 c.traps[DivisionByZero] = True
4791 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
4792 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
4793 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00004794
Stefan Krah1919b7e2012-03-21 18:25:23 +01004795 c.clear_flags()
4796 c.traps[InvalidOperation] = True
4797 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
4798 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
4799 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00004800
Stefan Krah1919b7e2012-03-21 18:25:23 +01004801 c.traps[InvalidOperation] = True
4802 c.prec = 2
4803 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00004804
Stefan Krah1919b7e2012-03-21 18:25:23 +01004805 @requires_extra_functionality
4806 def test_c_context_templates(self):
4807 self.assertEqual(
4808 C.BasicContext._traps,
4809 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
4810 C.DecUnderflow|C.DecClamped
4811 )
4812 self.assertEqual(
4813 C.DefaultContext._traps,
4814 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
4815 )
Mark Dickinson84230a12010-02-18 14:49:50 +00004816
Stefan Krah1919b7e2012-03-21 18:25:23 +01004817 @requires_extra_functionality
4818 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00004819
Stefan Krah1919b7e2012-03-21 18:25:23 +01004820 # SignalDict coverage
4821 Context = C.Context
4822 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00004823
Stefan Krah1919b7e2012-03-21 18:25:23 +01004824 InvalidOperation = C.InvalidOperation
4825 DivisionByZero = C.DivisionByZero
4826 Overflow = C.Overflow
4827 Subnormal = C.Subnormal
4828 Underflow = C.Underflow
4829 Rounded = C.Rounded
4830 Inexact = C.Inexact
4831 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00004832
Stefan Krah1919b7e2012-03-21 18:25:23 +01004833 DecClamped = C.DecClamped
4834 DecInvalidOperation = C.DecInvalidOperation
4835 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00004836
Stefan Krah1919b7e2012-03-21 18:25:23 +01004837 def assertIsExclusivelySet(signal, signal_dict):
4838 for sig in signal_dict:
4839 if sig == signal:
4840 self.assertTrue(signal_dict[sig])
4841 else:
4842 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00004843
Stefan Krah1919b7e2012-03-21 18:25:23 +01004844 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00004845
Stefan Krah1919b7e2012-03-21 18:25:23 +01004846 # Signal dict methods
4847 self.assertTrue(Overflow in c.traps)
4848 c.clear_traps()
4849 for k in c.traps.keys():
4850 c.traps[k] = True
4851 for v in c.traps.values():
4852 self.assertTrue(v)
4853 c.clear_traps()
4854 for k, v in c.traps.items():
4855 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00004856
Stefan Krah1919b7e2012-03-21 18:25:23 +01004857 self.assertFalse(c.flags.get(Overflow))
4858 self.assertIs(c.flags.get("x"), None)
4859 self.assertEqual(c.flags.get("x", "y"), "y")
4860 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00004861
Stefan Krah1919b7e2012-03-21 18:25:23 +01004862 self.assertEqual(len(c.flags), len(c.traps))
4863 s = sys.getsizeof(c.flags)
4864 s = sys.getsizeof(c.traps)
4865 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00004866
Stefan Krah1919b7e2012-03-21 18:25:23 +01004867 # Set flags/traps.
4868 c.clear_flags()
4869 c._flags = DecClamped
4870 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00004871
Stefan Krah1919b7e2012-03-21 18:25:23 +01004872 c.clear_traps()
4873 c._traps = DecInvalidOperation
4874 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00004875
Stefan Krah1919b7e2012-03-21 18:25:23 +01004876 # Set flags/traps from dictionary.
4877 c.clear_flags()
4878 d = c.flags.copy()
4879 d[DivisionByZero] = True
4880 c.flags = d
4881 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004882
Stefan Krah1919b7e2012-03-21 18:25:23 +01004883 c.clear_traps()
4884 d = c.traps.copy()
4885 d[Underflow] = True
4886 c.traps = d
4887 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004888
Stefan Krah1919b7e2012-03-21 18:25:23 +01004889 # Random constructors
4890 IntSignals = {
4891 Clamped: C.DecClamped,
4892 Rounded: C.DecRounded,
4893 Inexact: C.DecInexact,
4894 Subnormal: C.DecSubnormal,
4895 Underflow: C.DecUnderflow,
4896 Overflow: C.DecOverflow,
4897 DivisionByZero: C.DecDivisionByZero,
4898 InvalidOperation: C.DecIEEEInvalidOperation
4899 }
4900 IntCond = [
4901 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
4902 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
4903 C.DecConversionSyntax,
4904 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01004905
Stefan Krah1919b7e2012-03-21 18:25:23 +01004906 lim = len(OrderedSignals[C])
4907 for r in range(lim):
4908 for t in range(lim):
4909 for round in RoundingModes[C]:
4910 flags = random.sample(OrderedSignals[C], r)
4911 traps = random.sample(OrderedSignals[C], t)
4912 prec = random.randrange(1, 10000)
4913 emin = random.randrange(-10000, 0)
4914 emax = random.randrange(0, 10000)
4915 clamp = random.randrange(0, 2)
4916 caps = random.randrange(0, 2)
4917 cr = random.randrange(0, 2)
4918 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
4919 capitals=caps, clamp=clamp, flags=list(flags),
4920 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00004921
Stefan Krah1919b7e2012-03-21 18:25:23 +01004922 self.assertEqual(c.prec, prec)
4923 self.assertEqual(c.rounding, round)
4924 self.assertEqual(c.Emin, emin)
4925 self.assertEqual(c.Emax, emax)
4926 self.assertEqual(c.capitals, caps)
4927 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00004928
Stefan Krah1919b7e2012-03-21 18:25:23 +01004929 f = 0
4930 for x in flags:
4931 f |= IntSignals[x]
4932 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004933
Stefan Krah1919b7e2012-03-21 18:25:23 +01004934 f = 0
4935 for x in traps:
4936 f |= IntSignals[x]
4937 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004938
Stefan Krah1919b7e2012-03-21 18:25:23 +01004939 for cond in IntCond:
4940 c._flags = cond
4941 self.assertTrue(c._flags&DecIEEEInvalidOperation)
4942 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004943
Stefan Krah1919b7e2012-03-21 18:25:23 +01004944 for cond in IntCond:
4945 c._traps = cond
4946 self.assertTrue(c._traps&DecIEEEInvalidOperation)
4947 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004948
Stefan Krah1919b7e2012-03-21 18:25:23 +01004949 def test_invalid_override(self):
4950 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00004951
Stefan Krah1919b7e2012-03-21 18:25:23 +01004952 try:
4953 from locale import CHAR_MAX
4954 except ImportError:
4955 return
Mark Dickinson84230a12010-02-18 14:49:50 +00004956
Stefan Krah1919b7e2012-03-21 18:25:23 +01004957 def make_grouping(lst):
4958 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00004959
Stefan Krah1919b7e2012-03-21 18:25:23 +01004960 def get_fmt(x, override=None, fmt='n'):
4961 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004962
Stefan Krah1919b7e2012-03-21 18:25:23 +01004963 invalid_grouping = {
4964 'decimal_point' : ',',
4965 'grouping' : make_grouping([255, 255, 0]),
4966 'thousands_sep' : ','
4967 }
4968 invalid_dot = {
4969 'decimal_point' : 'xxxxx',
4970 'grouping' : make_grouping([3, 3, 0]),
4971 'thousands_sep' : ','
4972 }
4973 invalid_sep = {
4974 'decimal_point' : '.',
4975 'grouping' : make_grouping([3, 3, 0]),
4976 'thousands_sep' : 'yyyyy'
4977 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004978
Stefan Krah1919b7e2012-03-21 18:25:23 +01004979 if CHAR_MAX == 127: # negative grouping in override
4980 self.assertRaises(ValueError, get_fmt, 12345,
4981 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004982
Stefan Krah1919b7e2012-03-21 18:25:23 +01004983 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
4984 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004985
Stefan Krah0774e9b2012-04-05 15:21:58 +02004986 def test_exact_conversion(self):
4987 Decimal = C.Decimal
4988 localcontext = C.localcontext
4989 InvalidOperation = C.InvalidOperation
4990
4991 with localcontext() as c:
4992
4993 c.traps[InvalidOperation] = True
4994
4995 # Clamped
4996 x = "0e%d" % sys.maxsize
4997 self.assertRaises(InvalidOperation, Decimal, x)
4998
4999 x = "0e%d" % (-sys.maxsize-1)
5000 self.assertRaises(InvalidOperation, Decimal, x)
5001
5002 # Overflow
5003 x = "1e%d" % sys.maxsize
5004 self.assertRaises(InvalidOperation, Decimal, x)
5005
5006 # Underflow
5007 x = "1e%d" % (-sys.maxsize-1)
5008 self.assertRaises(InvalidOperation, Decimal, x)
5009
Stefan Krahff3eca02012-04-05 15:46:19 +02005010 def test_from_tuple(self):
5011 Decimal = C.Decimal
5012 localcontext = C.localcontext
5013 InvalidOperation = C.InvalidOperation
5014 Overflow = C.Overflow
5015 Underflow = C.Underflow
5016
5017 with localcontext() as c:
5018
5019 c.traps[InvalidOperation] = True
5020 c.traps[Overflow] = True
5021 c.traps[Underflow] = True
5022
5023 # SSIZE_MAX
5024 x = (1, (), sys.maxsize)
5025 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5026 self.assertRaises(InvalidOperation, Decimal, x)
5027
5028 x = (1, (0, 1, 2), sys.maxsize)
5029 self.assertRaises(Overflow, c.create_decimal, x)
5030 self.assertRaises(InvalidOperation, Decimal, x)
5031
5032 # SSIZE_MIN
5033 x = (1, (), -sys.maxsize-1)
5034 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5035 self.assertRaises(InvalidOperation, Decimal, x)
5036
5037 x = (1, (0, 1, 2), -sys.maxsize-1)
5038 self.assertRaises(Underflow, c.create_decimal, x)
5039 self.assertRaises(InvalidOperation, Decimal, x)
5040
5041 # OverflowError
5042 x = (1, (), sys.maxsize+1)
5043 self.assertRaises(OverflowError, c.create_decimal, x)
5044 self.assertRaises(OverflowError, Decimal, x)
5045
5046 x = (1, (), -sys.maxsize-2)
5047 self.assertRaises(OverflowError, c.create_decimal, x)
5048 self.assertRaises(OverflowError, Decimal, x)
5049
5050 # Specials
5051 x = (1, (), "N")
5052 self.assertEqual(str(Decimal(x)), '-sNaN')
5053 x = (1, (0,), "N")
5054 self.assertEqual(str(Decimal(x)), '-sNaN')
5055 x = (1, (0, 1), "N")
5056 self.assertEqual(str(Decimal(x)), '-sNaN1')
5057
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005058
Stefan Krah1919b7e2012-03-21 18:25:23 +01005059all_tests = [
5060 CExplicitConstructionTest, PyExplicitConstructionTest,
5061 CImplicitConstructionTest, PyImplicitConstructionTest,
5062 CFormatTest, PyFormatTest,
5063 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5064 CThreadingTest, PyThreadingTest,
5065 CUsabilityTest, PyUsabilityTest,
5066 CPythonAPItests, PyPythonAPItests,
5067 CContextAPItests, PyContextAPItests,
5068 CContextWithStatement, PyContextWithStatement,
5069 CContextFlags, PyContextFlags,
5070 CSpecialContexts, PySpecialContexts,
5071 CContextInputValidation, PyContextInputValidation,
5072 CContextSubclassing, PyContextSubclassing,
5073 CCoverage, PyCoverage,
5074 CFunctionality, PyFunctionality,
5075 CWhitebox, PyWhitebox,
5076 CIBMTestCases, PyIBMTestCases,
5077]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005078
Stefan Krah1919b7e2012-03-21 18:25:23 +01005079# Delete C tests if _decimal.so is not present.
5080if not C:
5081 all_tests = all_tests[1::2]
5082else:
5083 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005084
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005085
5086def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005087 """ Execute the tests.
5088
Raymond Hettingered20ad82004-09-04 20:09:13 +00005089 Runs all arithmetic tests if arith is True or if the "decimal" resource
5090 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005091 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005092
Stefan Krah1919b7e2012-03-21 18:25:23 +01005093 init(C)
5094 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005095 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00005096 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005097 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005098
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005099 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005100 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005101 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005102 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005103
5104 # Dynamically build custom test definition for each file in the test
5105 # directory and add the definitions to the DecimalTest class. This
5106 # procedure insures that new files do not get skipped.
5107 for filename in os.listdir(directory):
5108 if '.decTest' not in filename or filename.startswith("."):
5109 continue
5110 head, tail = filename.split('.')
5111 if todo_tests is not None and head not in todo_tests:
5112 continue
5113 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005114 setattr(CIBMTestCases, 'test_' + head, tester)
5115 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005116 del filename, head, tail, tester
5117
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005118
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005119 try:
5120 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005121 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005122 from doctest import IGNORE_EXCEPTION_DETAIL
5123 savedecimal = sys.modules['decimal']
5124 if C:
5125 sys.modules['decimal'] = C
5126 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5127 sys.modules['decimal'] = P
5128 run_doctest(P, verbose)
5129 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005130 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005131 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5132 P.setcontext(ORIGINAL_CONTEXT[P])
5133 if not C:
5134 warnings.warn('C tests skipped: no module named _decimal.',
5135 UserWarning)
5136 if not orig_sys_decimal is sys.modules['decimal']:
5137 raise TestFailed("Internal error: unbalanced number of changes to "
5138 "sys.modules['decimal'].")
5139
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005140
5141if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005142 import optparse
5143 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5144 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5145 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5146 (opt, args) = p.parse_args()
5147
5148 if opt.skip:
5149 test_main(arith=False, verbose=True)
5150 elif args:
5151 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005152 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005153 test_main(arith=True, verbose=True)