blob: b2ec1a6e07a6073bad932f741a18df13d65b1758 [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
1143 Decimal = self.decimal.Decimal
1144
Stefan Krah1919b7e2012-03-21 18:25:23 +01001145 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1146 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001147
1148class CFormatTest(FormatTest):
1149 decimal = C
1150class PyFormatTest(FormatTest):
1151 decimal = P
1152
1153class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001154 '''Unit tests for all arithmetic operators, binary and unary.'''
1155
1156 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001157 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001158
1159 d1 = Decimal('-11.1')
1160 d2 = Decimal('22.2')
1161
1162 #two Decimals
1163 self.assertEqual(d1+d2, Decimal('11.1'))
1164 self.assertEqual(d2+d1, Decimal('11.1'))
1165
1166 #with other type, left
1167 c = d1 + 5
1168 self.assertEqual(c, Decimal('-6.1'))
1169 self.assertEqual(type(c), type(d1))
1170
1171 #with other type, right
1172 c = 5 + d1
1173 self.assertEqual(c, Decimal('-6.1'))
1174 self.assertEqual(type(c), type(d1))
1175
1176 #inline with decimal
1177 d1 += d2
1178 self.assertEqual(d1, Decimal('11.1'))
1179
1180 #inline with other type
1181 d1 += 5
1182 self.assertEqual(d1, Decimal('16.1'))
1183
1184 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001185 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001186
1187 d1 = Decimal('-11.1')
1188 d2 = Decimal('22.2')
1189
1190 #two Decimals
1191 self.assertEqual(d1-d2, Decimal('-33.3'))
1192 self.assertEqual(d2-d1, Decimal('33.3'))
1193
1194 #with other type, left
1195 c = d1 - 5
1196 self.assertEqual(c, Decimal('-16.1'))
1197 self.assertEqual(type(c), type(d1))
1198
1199 #with other type, right
1200 c = 5 - d1
1201 self.assertEqual(c, Decimal('16.1'))
1202 self.assertEqual(type(c), type(d1))
1203
1204 #inline with decimal
1205 d1 -= d2
1206 self.assertEqual(d1, Decimal('-33.3'))
1207
1208 #inline with other type
1209 d1 -= 5
1210 self.assertEqual(d1, Decimal('-38.3'))
1211
1212 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001213 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001214
1215 d1 = Decimal('-5')
1216 d2 = Decimal('3')
1217
1218 #two Decimals
1219 self.assertEqual(d1*d2, Decimal('-15'))
1220 self.assertEqual(d2*d1, Decimal('-15'))
1221
1222 #with other type, left
1223 c = d1 * 5
1224 self.assertEqual(c, Decimal('-25'))
1225 self.assertEqual(type(c), type(d1))
1226
1227 #with other type, right
1228 c = 5 * d1
1229 self.assertEqual(c, Decimal('-25'))
1230 self.assertEqual(type(c), type(d1))
1231
1232 #inline with decimal
1233 d1 *= d2
1234 self.assertEqual(d1, Decimal('-15'))
1235
1236 #inline with other type
1237 d1 *= 5
1238 self.assertEqual(d1, Decimal('-75'))
1239
1240 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001241 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001242
1243 d1 = Decimal('-5')
1244 d2 = Decimal('2')
1245
1246 #two Decimals
1247 self.assertEqual(d1/d2, Decimal('-2.5'))
1248 self.assertEqual(d2/d1, Decimal('-0.4'))
1249
1250 #with other type, left
1251 c = d1 / 4
1252 self.assertEqual(c, Decimal('-1.25'))
1253 self.assertEqual(type(c), type(d1))
1254
1255 #with other type, right
1256 c = 4 / d1
1257 self.assertEqual(c, Decimal('-0.8'))
1258 self.assertEqual(type(c), type(d1))
1259
1260 #inline with decimal
1261 d1 /= d2
1262 self.assertEqual(d1, Decimal('-2.5'))
1263
1264 #inline with other type
1265 d1 /= 4
1266 self.assertEqual(d1, Decimal('-0.625'))
1267
1268 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001269 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001270
1271 d1 = Decimal('5')
1272 d2 = Decimal('2')
1273
1274 #two Decimals
1275 self.assertEqual(d1//d2, Decimal('2'))
1276 self.assertEqual(d2//d1, Decimal('0'))
1277
1278 #with other type, left
1279 c = d1 // 4
1280 self.assertEqual(c, Decimal('1'))
1281 self.assertEqual(type(c), type(d1))
1282
1283 #with other type, right
1284 c = 7 // d1
1285 self.assertEqual(c, Decimal('1'))
1286 self.assertEqual(type(c), type(d1))
1287
1288 #inline with decimal
1289 d1 //= d2
1290 self.assertEqual(d1, Decimal('2'))
1291
1292 #inline with other type
1293 d1 //= 2
1294 self.assertEqual(d1, Decimal('1'))
1295
1296 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001297 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001298
1299 d1 = Decimal('5')
1300 d2 = Decimal('2')
1301
1302 #two Decimals
1303 self.assertEqual(d1**d2, Decimal('25'))
1304 self.assertEqual(d2**d1, Decimal('32'))
1305
1306 #with other type, left
1307 c = d1 ** 4
1308 self.assertEqual(c, Decimal('625'))
1309 self.assertEqual(type(c), type(d1))
1310
1311 #with other type, right
1312 c = 7 ** d1
1313 self.assertEqual(c, Decimal('16807'))
1314 self.assertEqual(type(c), type(d1))
1315
1316 #inline with decimal
1317 d1 **= d2
1318 self.assertEqual(d1, Decimal('25'))
1319
1320 #inline with other type
1321 d1 **= 4
1322 self.assertEqual(d1, Decimal('390625'))
1323
1324 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001325 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001326
1327 d1 = Decimal('5')
1328 d2 = Decimal('2')
1329
1330 #two Decimals
1331 self.assertEqual(d1%d2, Decimal('1'))
1332 self.assertEqual(d2%d1, Decimal('2'))
1333
1334 #with other type, left
1335 c = d1 % 4
1336 self.assertEqual(c, Decimal('1'))
1337 self.assertEqual(type(c), type(d1))
1338
1339 #with other type, right
1340 c = 7 % d1
1341 self.assertEqual(c, Decimal('2'))
1342 self.assertEqual(type(c), type(d1))
1343
1344 #inline with decimal
1345 d1 %= d2
1346 self.assertEqual(d1, Decimal('1'))
1347
1348 #inline with other type
1349 d1 %= 4
1350 self.assertEqual(d1, Decimal('1'))
1351
1352 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001353 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001354
1355 d1 = Decimal('5')
1356 d2 = Decimal('2')
1357
1358 #two Decimals
1359 (p, q) = divmod(d1, d2)
1360 self.assertEqual(p, Decimal('2'))
1361 self.assertEqual(q, Decimal('1'))
1362 self.assertEqual(type(p), type(d1))
1363 self.assertEqual(type(q), type(d1))
1364
1365 #with other type, left
1366 (p, q) = divmod(d1, 4)
1367 self.assertEqual(p, Decimal('1'))
1368 self.assertEqual(q, Decimal('1'))
1369 self.assertEqual(type(p), type(d1))
1370 self.assertEqual(type(q), type(d1))
1371
1372 #with other type, right
1373 (p, q) = divmod(7, d1)
1374 self.assertEqual(p, Decimal('1'))
1375 self.assertEqual(q, Decimal('2'))
1376 self.assertEqual(type(p), type(d1))
1377 self.assertEqual(type(q), type(d1))
1378
1379 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001380 Decimal = self.decimal.Decimal
1381
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001382 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1383 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1384 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1385
Christian Heimes77c02eb2008-02-09 02:18:51 +00001386 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001387 # comparisons involving signaling nans signal InvalidOperation
1388
1389 # order comparisons (<, <=, >, >=) involving only quiet nans
1390 # also signal InvalidOperation
1391
1392 # equality comparisons (==, !=) involving only quiet nans
1393 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001394 Decimal = self.decimal.Decimal
1395 InvalidOperation = self.decimal.InvalidOperation
1396 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001397
Christian Heimes77c02eb2008-02-09 02:18:51 +00001398 n = Decimal('NaN')
1399 s = Decimal('sNaN')
1400 i = Decimal('Inf')
1401 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001402
1403 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1404 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1405 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1406 equality_ops = operator.eq, operator.ne
1407
1408 # results when InvalidOperation is not trapped
1409 for x, y in qnan_pairs + snan_pairs:
1410 for op in order_ops + equality_ops:
1411 got = op(x, y)
1412 expected = True if op is operator.ne else False
1413 self.assertIs(expected, got,
1414 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1415 "got {4!r}".format(
1416 expected, op.__name__, x, y, got))
1417
1418 # repeat the above, but this time trap the InvalidOperation
1419 with localcontext() as ctx:
1420 ctx.traps[InvalidOperation] = 1
1421
1422 for x, y in qnan_pairs:
1423 for op in equality_ops:
1424 got = op(x, y)
1425 expected = True if op is operator.ne else False
1426 self.assertIs(expected, got,
1427 "expected {0!r} for "
1428 "operator.{1}({2!r}, {3!r}); "
1429 "got {4!r}".format(
1430 expected, op.__name__, x, y, got))
1431
1432 for x, y in snan_pairs:
1433 for op in equality_ops:
1434 self.assertRaises(InvalidOperation, operator.eq, x, y)
1435 self.assertRaises(InvalidOperation, operator.ne, x, y)
1436
1437 for x, y in qnan_pairs + snan_pairs:
1438 for op in order_ops:
1439 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001440
Mark Dickinson84230a12010-02-18 14:49:50 +00001441 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001442 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001443
Stefan Krah1919b7e2012-03-21 18:25:23 +01001444 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001445 self.assertEqual(Decimal(1).copy_sign(-2), d)
1446 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1447
Stefan Krah1919b7e2012-03-21 18:25:23 +01001448class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1449 decimal = C
1450class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1451 decimal = P
1452
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001453# The following are two functions used to test threading in the next class
1454
1455def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001456 Decimal = cls.decimal.Decimal
1457 InvalidOperation = cls.decimal.InvalidOperation
1458 DivisionByZero = cls.decimal.DivisionByZero
1459 Overflow = cls.decimal.Overflow
1460 Underflow = cls.decimal.Underflow
1461 Inexact = cls.decimal.Inexact
1462 getcontext = cls.decimal.getcontext
1463 localcontext = cls.decimal.localcontext
1464
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001465 d1 = Decimal(1)
1466 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001467 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001468
Stefan Krah1919b7e2012-03-21 18:25:23 +01001469 cls.finish1.set()
1470 cls.synchro.wait()
1471
1472 test2 = d1/d3
1473 with localcontext() as c2:
1474 cls.assertTrue(c2.flags[Inexact])
1475 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1476 cls.assertTrue(c2.flags[DivisionByZero])
1477 with localcontext() as c3:
1478 cls.assertTrue(c3.flags[Inexact])
1479 cls.assertTrue(c3.flags[DivisionByZero])
1480 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1481 cls.assertTrue(c3.flags[InvalidOperation])
1482 del c3
1483 cls.assertFalse(c2.flags[InvalidOperation])
1484 del c2
1485
1486 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1487 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1488
1489 c1 = getcontext()
1490 cls.assertTrue(c1.flags[Inexact])
1491 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1492 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001493 return
1494
1495def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001496 Decimal = cls.decimal.Decimal
1497 InvalidOperation = cls.decimal.InvalidOperation
1498 DivisionByZero = cls.decimal.DivisionByZero
1499 Overflow = cls.decimal.Overflow
1500 Underflow = cls.decimal.Underflow
1501 Inexact = cls.decimal.Inexact
1502 getcontext = cls.decimal.getcontext
1503 localcontext = cls.decimal.localcontext
1504
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001505 d1 = Decimal(1)
1506 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001507 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001508
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001509 thiscontext = getcontext()
1510 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001511 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001512
1513 with localcontext() as c2:
1514 cls.assertTrue(c2.flags[Inexact])
1515 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1516 cls.assertTrue(c2.flags[Overflow])
1517 with localcontext(thiscontext) as c3:
1518 cls.assertTrue(c3.flags[Inexact])
1519 cls.assertFalse(c3.flags[Overflow])
1520 c3.traps[Underflow] = True
1521 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1522 cls.assertTrue(c3.flags[Underflow])
1523 del c3
1524 cls.assertFalse(c2.flags[Underflow])
1525 cls.assertFalse(c2.traps[Underflow])
1526 del c2
1527
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001528 cls.synchro.set()
1529 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001530
Stefan Krah1919b7e2012-03-21 18:25:23 +01001531 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001532 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001533
1534 cls.assertFalse(thiscontext.traps[Underflow])
1535 cls.assertTrue(thiscontext.flags[Inexact])
1536 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1537 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001538 return
1539
Stefan Krah1919b7e2012-03-21 18:25:23 +01001540class ThreadingTest(unittest.TestCase):
1541 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001542
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001543 # Take care executing this test from IDLE, there's an issue in threading
1544 # that hangs IDLE and I couldn't find it
1545
1546 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001547 DefaultContext = self.decimal.DefaultContext
1548
1549 if self.decimal == C and not self.decimal.HAVE_THREADS:
1550 self.skipTest("compiled without threading")
1551 # Test the "threading isolation" of a Context. Also test changing
1552 # the DefaultContext, which acts as a template for the thread-local
1553 # contexts.
1554 save_prec = DefaultContext.prec
1555 save_emax = DefaultContext.Emax
1556 save_emin = DefaultContext.Emin
1557 DefaultContext.prec = 24
1558 DefaultContext.Emax = 425000000
1559 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001560
1561 self.synchro = threading.Event()
1562 self.finish1 = threading.Event()
1563 self.finish2 = threading.Event()
1564
1565 th1 = threading.Thread(target=thfunc1, args=(self,))
1566 th2 = threading.Thread(target=thfunc2, args=(self,))
1567
1568 th1.start()
1569 th2.start()
1570
1571 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001572 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001573
1574 for sig in Signals[self.decimal]:
1575 self.assertFalse(DefaultContext.flags[sig])
1576
1577 DefaultContext.prec = save_prec
1578 DefaultContext.Emax = save_emax
1579 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001580 return
1581
Stefan Krah1919b7e2012-03-21 18:25:23 +01001582@unittest.skipUnless(threading, 'threading required')
1583class CThreadingTest(ThreadingTest):
1584 decimal = C
1585@unittest.skipUnless(threading, 'threading required')
1586class PyThreadingTest(ThreadingTest):
1587 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001588
Stefan Krah1919b7e2012-03-21 18:25:23 +01001589class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001590 '''Unit tests for Usability cases of Decimal.'''
1591
1592 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001593
Stefan Krah1919b7e2012-03-21 18:25:23 +01001594 Decimal = self.decimal.Decimal
1595
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001596 da = Decimal('23.42')
1597 db = Decimal('23.42')
1598 dc = Decimal('45')
1599
1600 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001601 self.assertGreater(dc, da)
1602 self.assertGreaterEqual(dc, da)
1603 self.assertLess(da, dc)
1604 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001605 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001606 self.assertNotEqual(da, dc)
1607 self.assertLessEqual(da, db)
1608 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001609
1610 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001611 self.assertGreater(dc, 23)
1612 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001613 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001614
1615 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001616 self.assertNotEqual(da, 'ugly')
1617 self.assertNotEqual(da, 32.7)
1618 self.assertNotEqual(da, object())
1619 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001620
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001621 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001622 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001623 b = a[:]
1624 random.shuffle(a)
1625 a.sort()
1626 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001627
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001628 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001629 Decimal = self.decimal.Decimal
1630
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001631 da = Decimal('0.25')
1632 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001633 self.assertLess(da, 3.0)
1634 self.assertLessEqual(da, 3.0)
1635 self.assertGreater(db, 0.25)
1636 self.assertGreaterEqual(db, 0.25)
1637 self.assertNotEqual(da, 1.5)
1638 self.assertEqual(da, 0.25)
1639 self.assertGreater(3.0, da)
1640 self.assertGreaterEqual(3.0, da)
1641 self.assertLess(0.25, db)
1642 self.assertLessEqual(0.25, db)
1643 self.assertNotEqual(0.25, db)
1644 self.assertEqual(3.0, db)
1645 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001646
Stefan Krah1919b7e2012-03-21 18:25:23 +01001647 def test_decimal_complex_comparison(self):
1648 Decimal = self.decimal.Decimal
1649
1650 da = Decimal('0.25')
1651 db = Decimal('3.0')
1652 self.assertNotEqual(da, (1.5+0j))
1653 self.assertNotEqual((1.5+0j), da)
1654 self.assertEqual(da, (0.25+0j))
1655 self.assertEqual((0.25+0j), da)
1656 self.assertEqual((3.0+0j), db)
1657 self.assertEqual(db, (3.0+0j))
1658
1659 self.assertNotEqual(db, (3.0+1j))
1660 self.assertNotEqual((3.0+1j), db)
1661
1662 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1663 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1664 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1665 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1666
1667 def test_decimal_fraction_comparison(self):
1668 D = self.decimal.Decimal
1669 F = fractions[self.decimal].Fraction
1670 Context = self.decimal.Context
1671 localcontext = self.decimal.localcontext
1672 InvalidOperation = self.decimal.InvalidOperation
1673
1674
1675 emax = C.MAX_EMAX if C else 999999999
1676 emin = C.MIN_EMIN if C else -999999999
1677 etiny = C.MIN_ETINY if C else -1999999997
1678 c = Context(Emax=emax, Emin=emin)
1679
1680 with localcontext(c):
1681 c.prec = emax
1682 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1683 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1684 self.assertLess(F(0,1), D("1e" + str(etiny)))
1685 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1686 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1687 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1688
1689 self.assertEqual(D("0.1"), F(1,10))
1690 self.assertEqual(F(1,10), D("0.1"))
1691
1692 c.prec = 300
1693 self.assertNotEqual(D(1)/3, F(1,3))
1694 self.assertNotEqual(F(1,3), D(1)/3)
1695
1696 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1697 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1698
1699 self.assertGreater(D('inf'), F(99999999999,123))
1700 self.assertGreater(D('inf'), F(-99999999999,123))
1701 self.assertLess(D('-inf'), F(99999999999,123))
1702 self.assertLess(D('-inf'), F(-99999999999,123))
1703
1704 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1705 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1706 self.assertNotEqual(D('nan'), F(-9,123))
1707 self.assertNotEqual(F(-9,123), D('nan'))
1708
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001709 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001710 Decimal = self.decimal.Decimal
1711
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001712 d = Decimal('43.24')
1713 c = copy.copy(d)
1714 self.assertEqual(id(c), id(d))
1715 dc = copy.deepcopy(d)
1716 self.assertEqual(id(dc), id(d))
1717
1718 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001719
1720 Decimal = self.decimal.Decimal
1721 localcontext = self.decimal.localcontext
1722
Stefan Krahdc817b22010-11-17 11:16:34 +00001723 def hashit(d):
1724 a = hash(d)
1725 b = d.__hash__()
1726 self.assertEqual(a, b)
1727 return a
1728
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001729 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001730 hashit(Decimal(23))
1731 hashit(Decimal('Infinity'))
1732 hashit(Decimal('-Infinity'))
1733 hashit(Decimal('nan123'))
1734 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001735
1736 test_values = [Decimal(sign*(2**m + n))
1737 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001738 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001739 for n in range(-10, 10)
1740 for sign in [-1, 1]]
1741 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001742 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001743 Decimal("-0"), # zeros
1744 Decimal("0.00"),
1745 Decimal("-0.000"),
1746 Decimal("0E10"),
1747 Decimal("-0E12"),
1748 Decimal("10.0"), # negative exponent
1749 Decimal("-23.00000"),
1750 Decimal("1230E100"), # positive exponent
1751 Decimal("-4.5678E50"),
1752 # a value for which hash(n) != hash(n % (2**64-1))
1753 # in Python pre-2.6
1754 Decimal(2**64 + 2**32 - 1),
1755 # selection of values which fail with the old (before
1756 # version 2.6) long.__hash__
1757 Decimal("1.634E100"),
1758 Decimal("90.697E100"),
1759 Decimal("188.83E100"),
1760 Decimal("1652.9E100"),
1761 Decimal("56531E100"),
1762 ])
1763
1764 # check that hash(d) == hash(int(d)) for integral values
1765 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001766 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001767
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001768 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001769 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001770 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001771 self.assertTrue(hashit(Decimal('Inf')))
1772 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001773
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001774 # check that the hashes of a Decimal float match when they
1775 # represent exactly the same values
1776 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1777 '34.0', '2.5', '112390.625', '-0.515625']
1778 for s in test_strings:
1779 f = float(s)
1780 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001781 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001782
Stefan Krah1919b7e2012-03-21 18:25:23 +01001783 with localcontext() as c:
1784 # check that the value of the hash doesn't depend on the
1785 # current context (issue #1757)
1786 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001787
Stefan Krah1919b7e2012-03-21 18:25:23 +01001788 c.prec = 6
1789 h1 = hashit(x)
1790 c.prec = 10
1791 h2 = hashit(x)
1792 c.prec = 16
1793 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001794
Stefan Krah1919b7e2012-03-21 18:25:23 +01001795 self.assertEqual(h1, h2)
1796 self.assertEqual(h1, h3)
1797
1798 c.prec = 10000
1799 x = 1100 ** 1248
1800 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001801
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001802 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001803 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001804
1805 d1 = Decimal('15.32')
1806 d2 = Decimal('28.5')
1807 l1 = 15
1808 l2 = 28
1809
1810 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001811 self.assertIs(min(d1,d2), d1)
1812 self.assertIs(min(d2,d1), d1)
1813 self.assertIs(max(d1,d2), d2)
1814 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001815
1816 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001817 self.assertIs(min(d1,l2), d1)
1818 self.assertIs(min(l2,d1), d1)
1819 self.assertIs(max(l1,d2), d2)
1820 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001821
1822 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001823 Decimal = self.decimal.Decimal
1824
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001825 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001826 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001827 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001828 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001829
1830 def test_tostring_methods(self):
1831 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001832 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001833
1834 d = Decimal('15.32')
1835 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001836 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001837
1838 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001839 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001840 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001841
1842 d1 = Decimal('66')
1843 d2 = Decimal('15.32')
1844
1845 #int
1846 self.assertEqual(int(d1), 66)
1847 self.assertEqual(int(d2), 15)
1848
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001849 #float
1850 self.assertEqual(float(d1), 66)
1851 self.assertEqual(float(d2), 15.32)
1852
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001853 #floor
1854 test_pairs = [
1855 ('123.00', 123),
1856 ('3.2', 3),
1857 ('3.54', 3),
1858 ('3.899', 3),
1859 ('-2.3', -3),
1860 ('-11.0', -11),
1861 ('0.0', 0),
1862 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001863 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001864 ]
1865 for d, i in test_pairs:
1866 self.assertEqual(math.floor(Decimal(d)), i)
1867 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1868 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1869 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1870 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1871 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1872
1873 #ceiling
1874 test_pairs = [
1875 ('123.00', 123),
1876 ('3.2', 4),
1877 ('3.54', 4),
1878 ('3.899', 4),
1879 ('-2.3', -2),
1880 ('-11.0', -11),
1881 ('0.0', 0),
1882 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001883 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001884 ]
1885 for d, i in test_pairs:
1886 self.assertEqual(math.ceil(Decimal(d)), i)
1887 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1888 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1889 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1890 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1891 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1892
1893 #round, single argument
1894 test_pairs = [
1895 ('123.00', 123),
1896 ('3.2', 3),
1897 ('3.54', 4),
1898 ('3.899', 4),
1899 ('-2.3', -2),
1900 ('-11.0', -11),
1901 ('0.0', 0),
1902 ('-0E3', 0),
1903 ('-3.5', -4),
1904 ('-2.5', -2),
1905 ('-1.5', -2),
1906 ('-0.5', 0),
1907 ('0.5', 0),
1908 ('1.5', 2),
1909 ('2.5', 2),
1910 ('3.5', 4),
1911 ]
1912 for d, i in test_pairs:
1913 self.assertEqual(round(Decimal(d)), i)
1914 self.assertRaises(ValueError, round, Decimal('-NaN'))
1915 self.assertRaises(ValueError, round, Decimal('sNaN'))
1916 self.assertRaises(ValueError, round, Decimal('NaN123'))
1917 self.assertRaises(OverflowError, round, Decimal('Inf'))
1918 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1919
1920 #round, two arguments; this is essentially equivalent
1921 #to quantize, which is already extensively tested
1922 test_triples = [
1923 ('123.456', -4, '0E+4'),
1924 ('123.456', -3, '0E+3'),
1925 ('123.456', -2, '1E+2'),
1926 ('123.456', -1, '1.2E+2'),
1927 ('123.456', 0, '123'),
1928 ('123.456', 1, '123.5'),
1929 ('123.456', 2, '123.46'),
1930 ('123.456', 3, '123.456'),
1931 ('123.456', 4, '123.4560'),
1932 ('123.455', 2, '123.46'),
1933 ('123.445', 2, '123.44'),
1934 ('Inf', 4, 'NaN'),
1935 ('-Inf', -23, 'NaN'),
1936 ('sNaN314', 3, 'NaN314'),
1937 ]
1938 for d, n, r in test_triples:
1939 self.assertEqual(str(round(Decimal(d), n)), r)
1940
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001941 def test_nan_to_float(self):
1942 # Test conversions of decimal NANs to float.
1943 # See http://bugs.python.org/issue15544
1944 Decimal = self.decimal.Decimal
1945 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1946 f = float(Decimal(s))
1947 self.assertTrue(math.isnan(f))
1948 sign = math.copysign(1.0, f)
1949 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1950
1951 def test_snan_to_float(self):
1952 Decimal = self.decimal.Decimal
1953 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1954 d = Decimal(s)
1955 self.assertRaises(ValueError, float, d)
1956
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001957 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001958 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001959
1960 #with zero
1961 d = Decimal( (0, (0,), 0) )
1962 self.assertEqual(d, eval(repr(d)))
1963
1964 #int
1965 d = Decimal( (1, (4, 5), 0) )
1966 self.assertEqual(d, eval(repr(d)))
1967
1968 #float
1969 d = Decimal( (0, (4, 5, 3, 4), -2) )
1970 self.assertEqual(d, eval(repr(d)))
1971
1972 #weird
1973 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1974 self.assertEqual(d, eval(repr(d)))
1975
1976 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001977 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001978
1979 #with zero
1980 d = Decimal(0)
1981 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1982
1983 #int
1984 d = Decimal(-45)
1985 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1986
1987 #complicated string
1988 d = Decimal("-4.34913534E-17")
1989 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1990
Stefan Krah76e12172012-09-10 19:34:58 +02001991 # The '0' coefficient is implementation specific to decimal.py.
1992 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001993 d = Decimal("Infinity")
1994 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1995
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001996 #leading zeros in coefficient should be stripped
1997 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1998 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1999 d = Decimal( (1, (0, 0, 0), 37) )
2000 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2001 d = Decimal( (1, (), 37) )
2002 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2003
2004 #leading zeros in NaN diagnostic info should be stripped
2005 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2006 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2007 d = Decimal( (1, (0, 0, 0), 'N') )
2008 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2009 d = Decimal( (1, (), 'n') )
2010 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2011
Stefan Krah76e12172012-09-10 19:34:58 +02002012 # For infinities, decimal.py has always silently accepted any
2013 # coefficient tuple.
2014 d = Decimal( (0, (0,), 'F') )
2015 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2016 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2017 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2018 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2019 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002020
Stefan Krah1919b7e2012-03-21 18:25:23 +01002021 def test_subclassing(self):
2022 # Different behaviours when subclassing Decimal
2023 Decimal = self.decimal.Decimal
2024
2025 class MyDecimal(Decimal):
2026 pass
2027
2028 d1 = MyDecimal(1)
2029 d2 = MyDecimal(2)
2030 d = d1 + d2
2031 self.assertIs(type(d), Decimal)
2032
2033 d = d1.max(d2)
2034 self.assertIs(type(d), Decimal)
2035
2036 d = copy.copy(d1)
2037 self.assertIs(type(d), MyDecimal)
2038 self.assertEqual(d, d1)
2039
2040 d = copy.deepcopy(d1)
2041 self.assertIs(type(d), MyDecimal)
2042 self.assertEqual(d, d1)
2043
2044 def test_implicit_context(self):
2045 Decimal = self.decimal.Decimal
2046 getcontext = self.decimal.getcontext
2047
2048 # Check results when context given implicitly. (Issue 2478)
2049 c = getcontext()
2050 self.assertEqual(str(Decimal(0).sqrt()),
2051 str(c.sqrt(Decimal(0))))
2052
2053 def test_conversions_from_int(self):
2054 # Check that methods taking a second Decimal argument will
2055 # always accept an integer in place of a Decimal.
2056 Decimal = self.decimal.Decimal
2057
2058 self.assertEqual(Decimal(4).compare(3),
2059 Decimal(4).compare(Decimal(3)))
2060 self.assertEqual(Decimal(4).compare_signal(3),
2061 Decimal(4).compare_signal(Decimal(3)))
2062 self.assertEqual(Decimal(4).compare_total(3),
2063 Decimal(4).compare_total(Decimal(3)))
2064 self.assertEqual(Decimal(4).compare_total_mag(3),
2065 Decimal(4).compare_total_mag(Decimal(3)))
2066 self.assertEqual(Decimal(10101).logical_and(1001),
2067 Decimal(10101).logical_and(Decimal(1001)))
2068 self.assertEqual(Decimal(10101).logical_or(1001),
2069 Decimal(10101).logical_or(Decimal(1001)))
2070 self.assertEqual(Decimal(10101).logical_xor(1001),
2071 Decimal(10101).logical_xor(Decimal(1001)))
2072 self.assertEqual(Decimal(567).max(123),
2073 Decimal(567).max(Decimal(123)))
2074 self.assertEqual(Decimal(567).max_mag(123),
2075 Decimal(567).max_mag(Decimal(123)))
2076 self.assertEqual(Decimal(567).min(123),
2077 Decimal(567).min(Decimal(123)))
2078 self.assertEqual(Decimal(567).min_mag(123),
2079 Decimal(567).min_mag(Decimal(123)))
2080 self.assertEqual(Decimal(567).next_toward(123),
2081 Decimal(567).next_toward(Decimal(123)))
2082 self.assertEqual(Decimal(1234).quantize(100),
2083 Decimal(1234).quantize(Decimal(100)))
2084 self.assertEqual(Decimal(768).remainder_near(1234),
2085 Decimal(768).remainder_near(Decimal(1234)))
2086 self.assertEqual(Decimal(123).rotate(1),
2087 Decimal(123).rotate(Decimal(1)))
2088 self.assertEqual(Decimal(1234).same_quantum(1000),
2089 Decimal(1234).same_quantum(Decimal(1000)))
2090 self.assertEqual(Decimal('9.123').scaleb(-100),
2091 Decimal('9.123').scaleb(Decimal(-100)))
2092 self.assertEqual(Decimal(456).shift(-1),
2093 Decimal(456).shift(Decimal(-1)))
2094
2095 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2096 Decimal(-12).fma(Decimal(45), Decimal(67)))
2097 self.assertEqual(Decimal(-12).fma(45, 67),
2098 Decimal(-12).fma(Decimal(45), Decimal(67)))
2099 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2100 Decimal(-12).fma(Decimal(45), Decimal(67)))
2101
2102class CUsabilityTest(UsabilityTest):
2103 decimal = C
2104class PyUsabilityTest(UsabilityTest):
2105 decimal = P
2106
2107class PythonAPItests(unittest.TestCase):
2108
2109 def test_abc(self):
2110 Decimal = self.decimal.Decimal
2111
2112 self.assertTrue(issubclass(Decimal, numbers.Number))
2113 self.assertFalse(issubclass(Decimal, numbers.Real))
2114 self.assertIsInstance(Decimal(0), numbers.Number)
2115 self.assertNotIsInstance(Decimal(0), numbers.Real)
2116
2117 def test_pickle(self):
2118 Decimal = self.decimal.Decimal
2119
2120 savedecimal = sys.modules['decimal']
2121
2122 # Round trip
2123 sys.modules['decimal'] = self.decimal
2124 d = Decimal('-3.141590000')
2125 p = pickle.dumps(d)
2126 e = pickle.loads(p)
2127 self.assertEqual(d, e)
2128
2129 if C:
2130 # Test interchangeability
2131 x = C.Decimal('-3.123e81723')
2132 y = P.Decimal('-3.123e81723')
2133
2134 sys.modules['decimal'] = C
2135 sx = pickle.dumps(x)
2136 sys.modules['decimal'] = P
2137 r = pickle.loads(sx)
2138 self.assertIsInstance(r, P.Decimal)
2139 self.assertEqual(r, y)
2140
2141 sys.modules['decimal'] = P
2142 sy = pickle.dumps(y)
2143 sys.modules['decimal'] = C
2144 r = pickle.loads(sy)
2145 self.assertIsInstance(r, C.Decimal)
2146 self.assertEqual(r, x)
2147
2148 sys.modules['decimal'] = savedecimal
2149
2150 def test_int(self):
2151 Decimal = self.decimal.Decimal
2152 ROUND_DOWN = self.decimal.ROUND_DOWN
2153
2154 for x in range(-250, 250):
2155 s = '%0.2f' % (x / 100.0)
2156 # should work the same as for floats
2157 self.assertEqual(int(Decimal(s)), int(float(s)))
2158 # should work the same as to_integral in the ROUND_DOWN mode
2159 d = Decimal(s)
2160 r = d.to_integral(ROUND_DOWN)
2161 self.assertEqual(Decimal(int(d)), r)
2162
2163 self.assertRaises(ValueError, int, Decimal('-nan'))
2164 self.assertRaises(ValueError, int, Decimal('snan'))
2165 self.assertRaises(OverflowError, int, Decimal('inf'))
2166 self.assertRaises(OverflowError, int, Decimal('-inf'))
2167
2168 def test_trunc(self):
2169 Decimal = self.decimal.Decimal
2170 ROUND_DOWN = self.decimal.ROUND_DOWN
2171
2172 for x in range(-250, 250):
2173 s = '%0.2f' % (x / 100.0)
2174 # should work the same as for floats
2175 self.assertEqual(int(Decimal(s)), int(float(s)))
2176 # should work the same as to_integral in the ROUND_DOWN mode
2177 d = Decimal(s)
2178 r = d.to_integral(ROUND_DOWN)
2179 self.assertEqual(Decimal(math.trunc(d)), r)
2180
2181 def test_from_float(self):
2182
2183 Decimal = self.decimal.Decimal
2184
2185 class MyDecimal(Decimal):
2186 pass
2187
2188 self.assertTrue(issubclass(MyDecimal, Decimal))
2189
2190 r = MyDecimal.from_float(0.1)
2191 self.assertEqual(type(r), MyDecimal)
2192 self.assertEqual(str(r),
2193 '0.1000000000000000055511151231257827021181583404541015625')
2194 bigint = 12345678901234567890123456789
2195 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2196 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2197 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2198 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2199 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2200 str(Decimal('NaN')))
2201 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2202 str(Decimal('Infinity')))
2203 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2204 str(Decimal('-Infinity')))
2205 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2206 for i in range(200):
2207 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2208 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2209
2210 def test_create_decimal_from_float(self):
2211 Decimal = self.decimal.Decimal
2212 Context = self.decimal.Context
2213 ROUND_DOWN = self.decimal.ROUND_DOWN
2214 ROUND_UP = self.decimal.ROUND_UP
2215 Inexact = self.decimal.Inexact
2216
2217 context = Context(prec=5, rounding=ROUND_DOWN)
2218 self.assertEqual(
2219 context.create_decimal_from_float(math.pi),
2220 Decimal('3.1415')
2221 )
2222 context = Context(prec=5, rounding=ROUND_UP)
2223 self.assertEqual(
2224 context.create_decimal_from_float(math.pi),
2225 Decimal('3.1416')
2226 )
2227 context = Context(prec=5, traps=[Inexact])
2228 self.assertRaises(
2229 Inexact,
2230 context.create_decimal_from_float,
2231 math.pi
2232 )
2233 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2234 "Decimal('-0')")
2235 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2236 "Decimal('1')")
2237 self.assertEqual(repr(context.create_decimal_from_float(10)),
2238 "Decimal('10')")
2239
2240 def test_quantize(self):
2241 Decimal = self.decimal.Decimal
2242 Context = self.decimal.Context
2243 InvalidOperation = self.decimal.InvalidOperation
2244 ROUND_DOWN = self.decimal.ROUND_DOWN
2245
2246 c = Context(Emax=99999, Emin=-99999)
2247 self.assertEqual(
2248 Decimal('7.335').quantize(Decimal('.01')),
2249 Decimal('7.34')
2250 )
2251 self.assertEqual(
2252 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2253 Decimal('7.33')
2254 )
2255 self.assertRaises(
2256 InvalidOperation,
2257 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2258 )
2259
2260 c = Context()
2261 d = Decimal("0.871831e800")
2262 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2263 self.assertEqual(x, Decimal('8.71E+799'))
2264
2265 def test_complex(self):
2266 Decimal = self.decimal.Decimal
2267
2268 x = Decimal("9.8182731e181273")
2269 self.assertEqual(x.real, x)
2270 self.assertEqual(x.imag, 0)
2271 self.assertEqual(x.conjugate(), x)
2272
2273 x = Decimal("1")
2274 self.assertEqual(complex(x), complex(float(1)))
2275
2276 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2277 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2278 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2279 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2280
2281 def test_named_parameters(self):
2282 D = self.decimal.Decimal
2283 Context = self.decimal.Context
2284 localcontext = self.decimal.localcontext
2285 InvalidOperation = self.decimal.InvalidOperation
2286 Overflow = self.decimal.Overflow
2287
2288 xc = Context()
2289 xc.prec = 1
2290 xc.Emax = 1
2291 xc.Emin = -1
2292
2293 with localcontext() as c:
2294 c.clear_flags()
2295
2296 self.assertEqual(D(9, xc), 9)
2297 self.assertEqual(D(9, context=xc), 9)
2298 self.assertEqual(D(context=xc, value=9), 9)
2299 self.assertEqual(D(context=xc), 0)
2300 xc.clear_flags()
2301 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2302 self.assertTrue(xc.flags[InvalidOperation])
2303 self.assertFalse(c.flags[InvalidOperation])
2304
2305 xc.clear_flags()
2306 self.assertEqual(D(2).exp(context=xc), 7)
2307 self.assertRaises(Overflow, D(8).exp, context=xc)
2308 self.assertTrue(xc.flags[Overflow])
2309 self.assertFalse(c.flags[Overflow])
2310
2311 xc.clear_flags()
2312 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2313 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2314 self.assertTrue(xc.flags[InvalidOperation])
2315 self.assertFalse(c.flags[InvalidOperation])
2316
2317 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2318 self.assertEqual(D(-1).next_minus(context=xc), -2)
2319 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2320 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2321 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2322 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2323 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2324 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2325
2326 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2327 xc.clear_flags()
2328 self.assertRaises(InvalidOperation,
2329 D("0").compare_signal, D('nan'), context=xc)
2330 self.assertTrue(xc.flags[InvalidOperation])
2331 self.assertFalse(c.flags[InvalidOperation])
2332 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2333 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2334 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2335 D('-0.3'))
2336 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2337 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2338 D('0.0'))
2339 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2340 xc.clear_flags()
2341 self.assertRaises(InvalidOperation,
2342 D("0.2").quantize, D('1e10'), context=xc)
2343 self.assertTrue(xc.flags[InvalidOperation])
2344 self.assertFalse(c.flags[InvalidOperation])
2345 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2346 D('-0.5'))
2347
2348 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2349 D('7E+1'))
2350
2351 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2352 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2353 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2354 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2355 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2356 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2357 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2358 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2359
2360 self.assertFalse(D("0.01").is_normal(context=xc))
2361 self.assertTrue(D("0.01").is_subnormal(context=xc))
2362
2363 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2364 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2365 self.assertRaises(TypeError, D(1).radix, context=xc)
2366
2367 self.assertEqual(D(-111).logb(context=xc), 2)
2368 self.assertEqual(D(0).logical_invert(context=xc), 1)
2369 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2370 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2371
2372 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2373 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2374 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2375 self.assertEqual(D('23').rotate(1, context=xc), 3)
2376 self.assertEqual(D('23').rotate(1, context=xc), 3)
2377 xc.clear_flags()
2378 self.assertRaises(Overflow,
2379 D('23').scaleb, 1, context=xc)
2380 self.assertTrue(xc.flags[Overflow])
2381 self.assertFalse(c.flags[Overflow])
2382 self.assertEqual(D('23').shift(-1, context=xc), 0)
2383
2384 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2385 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2386
2387 if (self.decimal == C):
2388 self.assertRaises(TypeError, D(1).canonical, context=xc)
2389 self.assertEqual(D("-1").copy_abs(context=xc), 1)
2390 self.assertEqual(D("1").copy_negate(context=xc), -1)
2391 else:
2392 self.assertEqual(D(1).canonical(context=xc), 1)
2393 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2394 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2395
Stefan Krahb6405ef2012-03-23 14:46:48 +01002396 def test_exception_hierarchy(self):
2397
2398 decimal = self.decimal
2399 DecimalException = decimal.DecimalException
2400 InvalidOperation = decimal.InvalidOperation
2401 FloatOperation = decimal.FloatOperation
2402 DivisionByZero = decimal.DivisionByZero
2403 Overflow = decimal.Overflow
2404 Underflow = decimal.Underflow
2405 Subnormal = decimal.Subnormal
2406 Inexact = decimal.Inexact
2407 Rounded = decimal.Rounded
2408 Clamped = decimal.Clamped
2409
2410 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2411
2412 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2413 self.assertTrue(issubclass(FloatOperation, DecimalException))
2414 self.assertTrue(issubclass(FloatOperation, TypeError))
2415 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2416 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2417 self.assertTrue(issubclass(Overflow, Rounded))
2418 self.assertTrue(issubclass(Overflow, Inexact))
2419 self.assertTrue(issubclass(Overflow, DecimalException))
2420 self.assertTrue(issubclass(Underflow, Inexact))
2421 self.assertTrue(issubclass(Underflow, Rounded))
2422 self.assertTrue(issubclass(Underflow, Subnormal))
2423 self.assertTrue(issubclass(Underflow, DecimalException))
2424
2425 self.assertTrue(issubclass(Subnormal, DecimalException))
2426 self.assertTrue(issubclass(Inexact, DecimalException))
2427 self.assertTrue(issubclass(Rounded, DecimalException))
2428 self.assertTrue(issubclass(Clamped, DecimalException))
2429
2430 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2431 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2432 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2433 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2434 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2435
Stefan Krah1919b7e2012-03-21 18:25:23 +01002436class CPythonAPItests(PythonAPItests):
2437 decimal = C
2438class PyPythonAPItests(PythonAPItests):
2439 decimal = P
2440
2441class ContextAPItests(unittest.TestCase):
2442
2443 def test_pickle(self):
2444
2445 Context = self.decimal.Context
2446
2447 savedecimal = sys.modules['decimal']
2448
2449 # Round trip
2450 sys.modules['decimal'] = self.decimal
2451 c = Context()
2452 e = pickle.loads(pickle.dumps(c))
2453
2454 self.assertEqual(c.prec, e.prec)
2455 self.assertEqual(c.Emin, e.Emin)
2456 self.assertEqual(c.Emax, e.Emax)
2457 self.assertEqual(c.rounding, e.rounding)
2458 self.assertEqual(c.capitals, e.capitals)
2459 self.assertEqual(c.clamp, e.clamp)
2460 self.assertEqual(c.flags, e.flags)
2461 self.assertEqual(c.traps, e.traps)
2462
2463 # Test interchangeability
2464 combinations = [(C, P), (P, C)] if C else [(P, P)]
2465 for dumper, loader in combinations:
2466 for ri, _ in enumerate(RoundingModes[dumper]):
2467 for fi, _ in enumerate(OrderedSignals[dumper]):
2468 for ti, _ in enumerate(OrderedSignals[dumper]):
2469
2470 prec = random.randrange(1, 100)
2471 emin = random.randrange(-100, 0)
2472 emax = random.randrange(1, 100)
2473 caps = random.randrange(2)
2474 clamp = random.randrange(2)
2475
2476 # One module dumps
2477 sys.modules['decimal'] = dumper
2478 c = dumper.Context(
2479 prec=prec, Emin=emin, Emax=emax,
2480 rounding=RoundingModes[dumper][ri],
2481 capitals=caps, clamp=clamp,
2482 flags=OrderedSignals[dumper][:fi],
2483 traps=OrderedSignals[dumper][:ti]
2484 )
2485 s = pickle.dumps(c)
2486
2487 # The other module loads
2488 sys.modules['decimal'] = loader
2489 d = pickle.loads(s)
2490 self.assertIsInstance(d, loader.Context)
2491
2492 self.assertEqual(d.prec, prec)
2493 self.assertEqual(d.Emin, emin)
2494 self.assertEqual(d.Emax, emax)
2495 self.assertEqual(d.rounding, RoundingModes[loader][ri])
2496 self.assertEqual(d.capitals, caps)
2497 self.assertEqual(d.clamp, clamp)
2498 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2499 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2500
2501 sys.modules['decimal'] = savedecimal
2502
2503 def test_equality_with_other_types(self):
2504 Decimal = self.decimal.Decimal
2505
2506 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2507 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2508
2509 def test_copy(self):
2510 # All copies should be deep
2511 Decimal = self.decimal.Decimal
2512 Context = self.decimal.Context
2513
2514 c = Context()
2515 d = c.copy()
2516 self.assertNotEqual(id(c), id(d))
2517 self.assertNotEqual(id(c.flags), id(d.flags))
2518 self.assertNotEqual(id(c.traps), id(d.traps))
2519 k1 = set(c.flags.keys())
2520 k2 = set(d.flags.keys())
2521 self.assertEqual(k1, k2)
2522 self.assertEqual(c.flags, d.flags)
2523
2524 def test__clamp(self):
2525 # In Python 3.2, the private attribute `_clamp` was made
2526 # public (issue 8540), with the old `_clamp` becoming a
2527 # property wrapping `clamp`. For the duration of Python 3.2
2528 # only, the attribute should be gettable/settable via both
2529 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2530 # removed.
2531 Context = self.decimal.Context
2532 c = Context()
2533 self.assertRaises(AttributeError, getattr, c, '_clamp')
2534
2535 def test_abs(self):
2536 Decimal = self.decimal.Decimal
2537 Context = self.decimal.Context
2538
2539 c = Context()
2540 d = c.abs(Decimal(-1))
2541 self.assertEqual(c.abs(-1), d)
2542 self.assertRaises(TypeError, c.abs, '-1')
2543
2544 def test_add(self):
2545 Decimal = self.decimal.Decimal
2546 Context = self.decimal.Context
2547
2548 c = Context()
2549 d = c.add(Decimal(1), Decimal(1))
2550 self.assertEqual(c.add(1, 1), d)
2551 self.assertEqual(c.add(Decimal(1), 1), d)
2552 self.assertEqual(c.add(1, Decimal(1)), d)
2553 self.assertRaises(TypeError, c.add, '1', 1)
2554 self.assertRaises(TypeError, c.add, 1, '1')
2555
2556 def test_compare(self):
2557 Decimal = self.decimal.Decimal
2558 Context = self.decimal.Context
2559
2560 c = Context()
2561 d = c.compare(Decimal(1), Decimal(1))
2562 self.assertEqual(c.compare(1, 1), d)
2563 self.assertEqual(c.compare(Decimal(1), 1), d)
2564 self.assertEqual(c.compare(1, Decimal(1)), d)
2565 self.assertRaises(TypeError, c.compare, '1', 1)
2566 self.assertRaises(TypeError, c.compare, 1, '1')
2567
2568 def test_compare_signal(self):
2569 Decimal = self.decimal.Decimal
2570 Context = self.decimal.Context
2571
2572 c = Context()
2573 d = c.compare_signal(Decimal(1), Decimal(1))
2574 self.assertEqual(c.compare_signal(1, 1), d)
2575 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2576 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2577 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2578 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2579
2580 def test_compare_total(self):
2581 Decimal = self.decimal.Decimal
2582 Context = self.decimal.Context
2583
2584 c = Context()
2585 d = c.compare_total(Decimal(1), Decimal(1))
2586 self.assertEqual(c.compare_total(1, 1), d)
2587 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2588 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2589 self.assertRaises(TypeError, c.compare_total, '1', 1)
2590 self.assertRaises(TypeError, c.compare_total, 1, '1')
2591
2592 def test_compare_total_mag(self):
2593 Decimal = self.decimal.Decimal
2594 Context = self.decimal.Context
2595
2596 c = Context()
2597 d = c.compare_total_mag(Decimal(1), Decimal(1))
2598 self.assertEqual(c.compare_total_mag(1, 1), d)
2599 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2600 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2601 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2602 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2603
2604 def test_copy_abs(self):
2605 Decimal = self.decimal.Decimal
2606 Context = self.decimal.Context
2607
2608 c = Context()
2609 d = c.copy_abs(Decimal(-1))
2610 self.assertEqual(c.copy_abs(-1), d)
2611 self.assertRaises(TypeError, c.copy_abs, '-1')
2612
2613 def test_copy_decimal(self):
2614 Decimal = self.decimal.Decimal
2615 Context = self.decimal.Context
2616
2617 c = Context()
2618 d = c.copy_decimal(Decimal(-1))
2619 self.assertEqual(c.copy_decimal(-1), d)
2620 self.assertRaises(TypeError, c.copy_decimal, '-1')
2621
2622 def test_copy_negate(self):
2623 Decimal = self.decimal.Decimal
2624 Context = self.decimal.Context
2625
2626 c = Context()
2627 d = c.copy_negate(Decimal(-1))
2628 self.assertEqual(c.copy_negate(-1), d)
2629 self.assertRaises(TypeError, c.copy_negate, '-1')
2630
2631 def test_copy_sign(self):
2632 Decimal = self.decimal.Decimal
2633 Context = self.decimal.Context
2634
2635 c = Context()
2636 d = c.copy_sign(Decimal(1), Decimal(-2))
2637 self.assertEqual(c.copy_sign(1, -2), d)
2638 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2639 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2640 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2641 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2642
2643 def test_divide(self):
2644 Decimal = self.decimal.Decimal
2645 Context = self.decimal.Context
2646
2647 c = Context()
2648 d = c.divide(Decimal(1), Decimal(2))
2649 self.assertEqual(c.divide(1, 2), d)
2650 self.assertEqual(c.divide(Decimal(1), 2), d)
2651 self.assertEqual(c.divide(1, Decimal(2)), d)
2652 self.assertRaises(TypeError, c.divide, '1', 2)
2653 self.assertRaises(TypeError, c.divide, 1, '2')
2654
2655 def test_divide_int(self):
2656 Decimal = self.decimal.Decimal
2657 Context = self.decimal.Context
2658
2659 c = Context()
2660 d = c.divide_int(Decimal(1), Decimal(2))
2661 self.assertEqual(c.divide_int(1, 2), d)
2662 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2663 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2664 self.assertRaises(TypeError, c.divide_int, '1', 2)
2665 self.assertRaises(TypeError, c.divide_int, 1, '2')
2666
2667 def test_divmod(self):
2668 Decimal = self.decimal.Decimal
2669 Context = self.decimal.Context
2670
2671 c = Context()
2672 d = c.divmod(Decimal(1), Decimal(2))
2673 self.assertEqual(c.divmod(1, 2), d)
2674 self.assertEqual(c.divmod(Decimal(1), 2), d)
2675 self.assertEqual(c.divmod(1, Decimal(2)), d)
2676 self.assertRaises(TypeError, c.divmod, '1', 2)
2677 self.assertRaises(TypeError, c.divmod, 1, '2')
2678
2679 def test_exp(self):
2680 Decimal = self.decimal.Decimal
2681 Context = self.decimal.Context
2682
2683 c = Context()
2684 d = c.exp(Decimal(10))
2685 self.assertEqual(c.exp(10), d)
2686 self.assertRaises(TypeError, c.exp, '10')
2687
2688 def test_fma(self):
2689 Decimal = self.decimal.Decimal
2690 Context = self.decimal.Context
2691
2692 c = Context()
2693 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
2694 self.assertEqual(c.fma(2, 3, 4), d)
2695 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
2696 self.assertEqual(c.fma(2, Decimal(3), 4), d)
2697 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
2698 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
2699 self.assertRaises(TypeError, c.fma, '2', 3, 4)
2700 self.assertRaises(TypeError, c.fma, 2, '3', 4)
2701 self.assertRaises(TypeError, c.fma, 2, 3, '4')
2702
2703 # Issue 12079 for Context.fma ...
2704 self.assertRaises(TypeError, c.fma,
2705 Decimal('Infinity'), Decimal(0), "not a decimal")
2706 self.assertRaises(TypeError, c.fma,
2707 Decimal(1), Decimal('snan'), 1.222)
2708 # ... and for Decimal.fma.
2709 self.assertRaises(TypeError, Decimal('Infinity').fma,
2710 Decimal(0), "not a decimal")
2711 self.assertRaises(TypeError, Decimal(1).fma,
2712 Decimal('snan'), 1.222)
2713
2714 def test_is_finite(self):
2715 Decimal = self.decimal.Decimal
2716 Context = self.decimal.Context
2717
2718 c = Context()
2719 d = c.is_finite(Decimal(10))
2720 self.assertEqual(c.is_finite(10), d)
2721 self.assertRaises(TypeError, c.is_finite, '10')
2722
2723 def test_is_infinite(self):
2724 Decimal = self.decimal.Decimal
2725 Context = self.decimal.Context
2726
2727 c = Context()
2728 d = c.is_infinite(Decimal(10))
2729 self.assertEqual(c.is_infinite(10), d)
2730 self.assertRaises(TypeError, c.is_infinite, '10')
2731
2732 def test_is_nan(self):
2733 Decimal = self.decimal.Decimal
2734 Context = self.decimal.Context
2735
2736 c = Context()
2737 d = c.is_nan(Decimal(10))
2738 self.assertEqual(c.is_nan(10), d)
2739 self.assertRaises(TypeError, c.is_nan, '10')
2740
2741 def test_is_normal(self):
2742 Decimal = self.decimal.Decimal
2743 Context = self.decimal.Context
2744
2745 c = Context()
2746 d = c.is_normal(Decimal(10))
2747 self.assertEqual(c.is_normal(10), d)
2748 self.assertRaises(TypeError, c.is_normal, '10')
2749
2750 def test_is_qnan(self):
2751 Decimal = self.decimal.Decimal
2752 Context = self.decimal.Context
2753
2754 c = Context()
2755 d = c.is_qnan(Decimal(10))
2756 self.assertEqual(c.is_qnan(10), d)
2757 self.assertRaises(TypeError, c.is_qnan, '10')
2758
2759 def test_is_signed(self):
2760 Decimal = self.decimal.Decimal
2761 Context = self.decimal.Context
2762
2763 c = Context()
2764 d = c.is_signed(Decimal(10))
2765 self.assertEqual(c.is_signed(10), d)
2766 self.assertRaises(TypeError, c.is_signed, '10')
2767
2768 def test_is_snan(self):
2769 Decimal = self.decimal.Decimal
2770 Context = self.decimal.Context
2771
2772 c = Context()
2773 d = c.is_snan(Decimal(10))
2774 self.assertEqual(c.is_snan(10), d)
2775 self.assertRaises(TypeError, c.is_snan, '10')
2776
2777 def test_is_subnormal(self):
2778 Decimal = self.decimal.Decimal
2779 Context = self.decimal.Context
2780
2781 c = Context()
2782 d = c.is_subnormal(Decimal(10))
2783 self.assertEqual(c.is_subnormal(10), d)
2784 self.assertRaises(TypeError, c.is_subnormal, '10')
2785
2786 def test_is_zero(self):
2787 Decimal = self.decimal.Decimal
2788 Context = self.decimal.Context
2789
2790 c = Context()
2791 d = c.is_zero(Decimal(10))
2792 self.assertEqual(c.is_zero(10), d)
2793 self.assertRaises(TypeError, c.is_zero, '10')
2794
2795 def test_ln(self):
2796 Decimal = self.decimal.Decimal
2797 Context = self.decimal.Context
2798
2799 c = Context()
2800 d = c.ln(Decimal(10))
2801 self.assertEqual(c.ln(10), d)
2802 self.assertRaises(TypeError, c.ln, '10')
2803
2804 def test_log10(self):
2805 Decimal = self.decimal.Decimal
2806 Context = self.decimal.Context
2807
2808 c = Context()
2809 d = c.log10(Decimal(10))
2810 self.assertEqual(c.log10(10), d)
2811 self.assertRaises(TypeError, c.log10, '10')
2812
2813 def test_logb(self):
2814 Decimal = self.decimal.Decimal
2815 Context = self.decimal.Context
2816
2817 c = Context()
2818 d = c.logb(Decimal(10))
2819 self.assertEqual(c.logb(10), d)
2820 self.assertRaises(TypeError, c.logb, '10')
2821
2822 def test_logical_and(self):
2823 Decimal = self.decimal.Decimal
2824 Context = self.decimal.Context
2825
2826 c = Context()
2827 d = c.logical_and(Decimal(1), Decimal(1))
2828 self.assertEqual(c.logical_and(1, 1), d)
2829 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2830 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2831 self.assertRaises(TypeError, c.logical_and, '1', 1)
2832 self.assertRaises(TypeError, c.logical_and, 1, '1')
2833
2834 def test_logical_invert(self):
2835 Decimal = self.decimal.Decimal
2836 Context = self.decimal.Context
2837
2838 c = Context()
2839 d = c.logical_invert(Decimal(1000))
2840 self.assertEqual(c.logical_invert(1000), d)
2841 self.assertRaises(TypeError, c.logical_invert, '1000')
2842
2843 def test_logical_or(self):
2844 Decimal = self.decimal.Decimal
2845 Context = self.decimal.Context
2846
2847 c = Context()
2848 d = c.logical_or(Decimal(1), Decimal(1))
2849 self.assertEqual(c.logical_or(1, 1), d)
2850 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2851 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2852 self.assertRaises(TypeError, c.logical_or, '1', 1)
2853 self.assertRaises(TypeError, c.logical_or, 1, '1')
2854
2855 def test_logical_xor(self):
2856 Decimal = self.decimal.Decimal
2857 Context = self.decimal.Context
2858
2859 c = Context()
2860 d = c.logical_xor(Decimal(1), Decimal(1))
2861 self.assertEqual(c.logical_xor(1, 1), d)
2862 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2863 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2864 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2865 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2866
2867 def test_max(self):
2868 Decimal = self.decimal.Decimal
2869 Context = self.decimal.Context
2870
2871 c = Context()
2872 d = c.max(Decimal(1), Decimal(2))
2873 self.assertEqual(c.max(1, 2), d)
2874 self.assertEqual(c.max(Decimal(1), 2), d)
2875 self.assertEqual(c.max(1, Decimal(2)), d)
2876 self.assertRaises(TypeError, c.max, '1', 2)
2877 self.assertRaises(TypeError, c.max, 1, '2')
2878
2879 def test_max_mag(self):
2880 Decimal = self.decimal.Decimal
2881 Context = self.decimal.Context
2882
2883 c = Context()
2884 d = c.max_mag(Decimal(1), Decimal(2))
2885 self.assertEqual(c.max_mag(1, 2), d)
2886 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2887 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2888 self.assertRaises(TypeError, c.max_mag, '1', 2)
2889 self.assertRaises(TypeError, c.max_mag, 1, '2')
2890
2891 def test_min(self):
2892 Decimal = self.decimal.Decimal
2893 Context = self.decimal.Context
2894
2895 c = Context()
2896 d = c.min(Decimal(1), Decimal(2))
2897 self.assertEqual(c.min(1, 2), d)
2898 self.assertEqual(c.min(Decimal(1), 2), d)
2899 self.assertEqual(c.min(1, Decimal(2)), d)
2900 self.assertRaises(TypeError, c.min, '1', 2)
2901 self.assertRaises(TypeError, c.min, 1, '2')
2902
2903 def test_min_mag(self):
2904 Decimal = self.decimal.Decimal
2905 Context = self.decimal.Context
2906
2907 c = Context()
2908 d = c.min_mag(Decimal(1), Decimal(2))
2909 self.assertEqual(c.min_mag(1, 2), d)
2910 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2911 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2912 self.assertRaises(TypeError, c.min_mag, '1', 2)
2913 self.assertRaises(TypeError, c.min_mag, 1, '2')
2914
2915 def test_minus(self):
2916 Decimal = self.decimal.Decimal
2917 Context = self.decimal.Context
2918
2919 c = Context()
2920 d = c.minus(Decimal(10))
2921 self.assertEqual(c.minus(10), d)
2922 self.assertRaises(TypeError, c.minus, '10')
2923
2924 def test_multiply(self):
2925 Decimal = self.decimal.Decimal
2926 Context = self.decimal.Context
2927
2928 c = Context()
2929 d = c.multiply(Decimal(1), Decimal(2))
2930 self.assertEqual(c.multiply(1, 2), d)
2931 self.assertEqual(c.multiply(Decimal(1), 2), d)
2932 self.assertEqual(c.multiply(1, Decimal(2)), d)
2933 self.assertRaises(TypeError, c.multiply, '1', 2)
2934 self.assertRaises(TypeError, c.multiply, 1, '2')
2935
2936 def test_next_minus(self):
2937 Decimal = self.decimal.Decimal
2938 Context = self.decimal.Context
2939
2940 c = Context()
2941 d = c.next_minus(Decimal(10))
2942 self.assertEqual(c.next_minus(10), d)
2943 self.assertRaises(TypeError, c.next_minus, '10')
2944
2945 def test_next_plus(self):
2946 Decimal = self.decimal.Decimal
2947 Context = self.decimal.Context
2948
2949 c = Context()
2950 d = c.next_plus(Decimal(10))
2951 self.assertEqual(c.next_plus(10), d)
2952 self.assertRaises(TypeError, c.next_plus, '10')
2953
2954 def test_next_toward(self):
2955 Decimal = self.decimal.Decimal
2956 Context = self.decimal.Context
2957
2958 c = Context()
2959 d = c.next_toward(Decimal(1), Decimal(2))
2960 self.assertEqual(c.next_toward(1, 2), d)
2961 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2962 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2963 self.assertRaises(TypeError, c.next_toward, '1', 2)
2964 self.assertRaises(TypeError, c.next_toward, 1, '2')
2965
2966 def test_normalize(self):
2967 Decimal = self.decimal.Decimal
2968 Context = self.decimal.Context
2969
2970 c = Context()
2971 d = c.normalize(Decimal(10))
2972 self.assertEqual(c.normalize(10), d)
2973 self.assertRaises(TypeError, c.normalize, '10')
2974
2975 def test_number_class(self):
2976 Decimal = self.decimal.Decimal
2977 Context = self.decimal.Context
2978
2979 c = Context()
2980 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2981 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2982 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2983
2984 def test_plus(self):
2985 Decimal = self.decimal.Decimal
2986 Context = self.decimal.Context
2987
2988 c = Context()
2989 d = c.plus(Decimal(10))
2990 self.assertEqual(c.plus(10), d)
2991 self.assertRaises(TypeError, c.plus, '10')
2992
2993 def test_power(self):
2994 Decimal = self.decimal.Decimal
2995 Context = self.decimal.Context
2996
2997 c = Context()
2998 d = c.power(Decimal(1), Decimal(4))
2999 self.assertEqual(c.power(1, 4), d)
3000 self.assertEqual(c.power(Decimal(1), 4), d)
3001 self.assertEqual(c.power(1, Decimal(4)), d)
3002 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3003 self.assertRaises(TypeError, c.power, '1', 4)
3004 self.assertRaises(TypeError, c.power, 1, '4')
3005 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3006
3007 def test_quantize(self):
3008 Decimal = self.decimal.Decimal
3009 Context = self.decimal.Context
3010
3011 c = Context()
3012 d = c.quantize(Decimal(1), Decimal(2))
3013 self.assertEqual(c.quantize(1, 2), d)
3014 self.assertEqual(c.quantize(Decimal(1), 2), d)
3015 self.assertEqual(c.quantize(1, Decimal(2)), d)
3016 self.assertRaises(TypeError, c.quantize, '1', 2)
3017 self.assertRaises(TypeError, c.quantize, 1, '2')
3018
3019 def test_remainder(self):
3020 Decimal = self.decimal.Decimal
3021 Context = self.decimal.Context
3022
3023 c = Context()
3024 d = c.remainder(Decimal(1), Decimal(2))
3025 self.assertEqual(c.remainder(1, 2), d)
3026 self.assertEqual(c.remainder(Decimal(1), 2), d)
3027 self.assertEqual(c.remainder(1, Decimal(2)), d)
3028 self.assertRaises(TypeError, c.remainder, '1', 2)
3029 self.assertRaises(TypeError, c.remainder, 1, '2')
3030
3031 def test_remainder_near(self):
3032 Decimal = self.decimal.Decimal
3033 Context = self.decimal.Context
3034
3035 c = Context()
3036 d = c.remainder_near(Decimal(1), Decimal(2))
3037 self.assertEqual(c.remainder_near(1, 2), d)
3038 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3039 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3040 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3041 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3042
3043 def test_rotate(self):
3044 Decimal = self.decimal.Decimal
3045 Context = self.decimal.Context
3046
3047 c = Context()
3048 d = c.rotate(Decimal(1), Decimal(2))
3049 self.assertEqual(c.rotate(1, 2), d)
3050 self.assertEqual(c.rotate(Decimal(1), 2), d)
3051 self.assertEqual(c.rotate(1, Decimal(2)), d)
3052 self.assertRaises(TypeError, c.rotate, '1', 2)
3053 self.assertRaises(TypeError, c.rotate, 1, '2')
3054
3055 def test_sqrt(self):
3056 Decimal = self.decimal.Decimal
3057 Context = self.decimal.Context
3058
3059 c = Context()
3060 d = c.sqrt(Decimal(10))
3061 self.assertEqual(c.sqrt(10), d)
3062 self.assertRaises(TypeError, c.sqrt, '10')
3063
3064 def test_same_quantum(self):
3065 Decimal = self.decimal.Decimal
3066 Context = self.decimal.Context
3067
3068 c = Context()
3069 d = c.same_quantum(Decimal(1), Decimal(2))
3070 self.assertEqual(c.same_quantum(1, 2), d)
3071 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3072 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3073 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3074 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3075
3076 def test_scaleb(self):
3077 Decimal = self.decimal.Decimal
3078 Context = self.decimal.Context
3079
3080 c = Context()
3081 d = c.scaleb(Decimal(1), Decimal(2))
3082 self.assertEqual(c.scaleb(1, 2), d)
3083 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3084 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3085 self.assertRaises(TypeError, c.scaleb, '1', 2)
3086 self.assertRaises(TypeError, c.scaleb, 1, '2')
3087
3088 def test_shift(self):
3089 Decimal = self.decimal.Decimal
3090 Context = self.decimal.Context
3091
3092 c = Context()
3093 d = c.shift(Decimal(1), Decimal(2))
3094 self.assertEqual(c.shift(1, 2), d)
3095 self.assertEqual(c.shift(Decimal(1), 2), d)
3096 self.assertEqual(c.shift(1, Decimal(2)), d)
3097 self.assertRaises(TypeError, c.shift, '1', 2)
3098 self.assertRaises(TypeError, c.shift, 1, '2')
3099
3100 def test_subtract(self):
3101 Decimal = self.decimal.Decimal
3102 Context = self.decimal.Context
3103
3104 c = Context()
3105 d = c.subtract(Decimal(1), Decimal(2))
3106 self.assertEqual(c.subtract(1, 2), d)
3107 self.assertEqual(c.subtract(Decimal(1), 2), d)
3108 self.assertEqual(c.subtract(1, Decimal(2)), d)
3109 self.assertRaises(TypeError, c.subtract, '1', 2)
3110 self.assertRaises(TypeError, c.subtract, 1, '2')
3111
3112 def test_to_eng_string(self):
3113 Decimal = self.decimal.Decimal
3114 Context = self.decimal.Context
3115
3116 c = Context()
3117 d = c.to_eng_string(Decimal(10))
3118 self.assertEqual(c.to_eng_string(10), d)
3119 self.assertRaises(TypeError, c.to_eng_string, '10')
3120
3121 def test_to_sci_string(self):
3122 Decimal = self.decimal.Decimal
3123 Context = self.decimal.Context
3124
3125 c = Context()
3126 d = c.to_sci_string(Decimal(10))
3127 self.assertEqual(c.to_sci_string(10), d)
3128 self.assertRaises(TypeError, c.to_sci_string, '10')
3129
3130 def test_to_integral_exact(self):
3131 Decimal = self.decimal.Decimal
3132 Context = self.decimal.Context
3133
3134 c = Context()
3135 d = c.to_integral_exact(Decimal(10))
3136 self.assertEqual(c.to_integral_exact(10), d)
3137 self.assertRaises(TypeError, c.to_integral_exact, '10')
3138
3139 def test_to_integral_value(self):
3140 Decimal = self.decimal.Decimal
3141 Context = self.decimal.Context
3142
3143 c = Context()
3144 d = c.to_integral_value(Decimal(10))
3145 self.assertEqual(c.to_integral_value(10), d)
3146 self.assertRaises(TypeError, c.to_integral_value, '10')
3147 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3148
3149class CContextAPItests(ContextAPItests):
3150 decimal = C
3151class PyContextAPItests(ContextAPItests):
3152 decimal = P
3153
3154class ContextWithStatement(unittest.TestCase):
3155 # Can't do these as docstrings until Python 2.6
3156 # as doctest can't handle __future__ statements
3157
3158 def test_localcontext(self):
3159 # Use a copy of the current context in the block
3160 getcontext = self.decimal.getcontext
3161 localcontext = self.decimal.localcontext
3162
3163 orig_ctx = getcontext()
3164 with localcontext() as enter_ctx:
3165 set_ctx = getcontext()
3166 final_ctx = getcontext()
3167 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3168 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3169 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3170
3171 def test_localcontextarg(self):
3172 # Use a copy of the supplied context in the block
3173 Context = self.decimal.Context
3174 getcontext = self.decimal.getcontext
3175 localcontext = self.decimal.localcontext
3176
3177 localcontext = self.decimal.localcontext
3178 orig_ctx = getcontext()
3179 new_ctx = Context(prec=42)
3180 with localcontext(new_ctx) as enter_ctx:
3181 set_ctx = getcontext()
3182 final_ctx = getcontext()
3183 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3184 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3185 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3186 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3187
3188 def test_nested_with_statements(self):
3189 # Use a copy of the supplied context in the block
3190 Decimal = self.decimal.Decimal
3191 Context = self.decimal.Context
3192 getcontext = self.decimal.getcontext
3193 localcontext = self.decimal.localcontext
3194 Clamped = self.decimal.Clamped
3195 Overflow = self.decimal.Overflow
3196
3197 orig_ctx = getcontext()
3198 orig_ctx.clear_flags()
3199 new_ctx = Context(Emax=384)
3200 with localcontext() as c1:
3201 self.assertEqual(c1.flags, orig_ctx.flags)
3202 self.assertEqual(c1.traps, orig_ctx.traps)
3203 c1.traps[Clamped] = True
3204 c1.Emin = -383
3205 self.assertNotEqual(orig_ctx.Emin, -383)
3206 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3207 self.assertTrue(c1.flags[Clamped])
3208 with localcontext(new_ctx) as c2:
3209 self.assertEqual(c2.flags, new_ctx.flags)
3210 self.assertEqual(c2.traps, new_ctx.traps)
3211 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3212 self.assertFalse(c2.flags[Clamped])
3213 self.assertTrue(c2.flags[Overflow])
3214 del c2
3215 self.assertFalse(c1.flags[Overflow])
3216 del c1
3217 self.assertNotEqual(orig_ctx.Emin, -383)
3218 self.assertFalse(orig_ctx.flags[Clamped])
3219 self.assertFalse(orig_ctx.flags[Overflow])
3220 self.assertFalse(new_ctx.flags[Clamped])
3221 self.assertFalse(new_ctx.flags[Overflow])
3222
3223 def test_with_statements_gc1(self):
3224 localcontext = self.decimal.localcontext
3225
3226 with localcontext() as c1:
3227 del c1
3228 with localcontext() as c2:
3229 del c2
3230 with localcontext() as c3:
3231 del c3
3232 with localcontext() as c4:
3233 del c4
3234
3235 def test_with_statements_gc2(self):
3236 localcontext = self.decimal.localcontext
3237
3238 with localcontext() as c1:
3239 with localcontext(c1) as c2:
3240 del c1
3241 with localcontext(c2) as c3:
3242 del c2
3243 with localcontext(c3) as c4:
3244 del c3
3245 del c4
3246
3247 def test_with_statements_gc3(self):
3248 Context = self.decimal.Context
3249 localcontext = self.decimal.localcontext
3250 getcontext = self.decimal.getcontext
3251 setcontext = self.decimal.setcontext
3252
3253 with localcontext() as c1:
3254 del c1
3255 n1 = Context(prec=1)
3256 setcontext(n1)
3257 with localcontext(n1) as c2:
3258 del n1
3259 self.assertEqual(c2.prec, 1)
3260 del c2
3261 n2 = Context(prec=2)
3262 setcontext(n2)
3263 del n2
3264 self.assertEqual(getcontext().prec, 2)
3265 n3 = Context(prec=3)
3266 setcontext(n3)
3267 self.assertEqual(getcontext().prec, 3)
3268 with localcontext(n3) as c3:
3269 del n3
3270 self.assertEqual(c3.prec, 3)
3271 del c3
3272 n4 = Context(prec=4)
3273 setcontext(n4)
3274 del n4
3275 self.assertEqual(getcontext().prec, 4)
3276 with localcontext() as c4:
3277 self.assertEqual(c4.prec, 4)
3278 del c4
3279
3280class CContextWithStatement(ContextWithStatement):
3281 decimal = C
3282class PyContextWithStatement(ContextWithStatement):
3283 decimal = P
3284
3285class ContextFlags(unittest.TestCase):
3286
3287 def test_flags_irrelevant(self):
3288 # check that the result (numeric result + flags raised) of an
3289 # arithmetic operation doesn't depend on the current flags
3290 Decimal = self.decimal.Decimal
3291 Context = self.decimal.Context
3292 Inexact = self.decimal.Inexact
3293 Rounded = self.decimal.Rounded
3294 Underflow = self.decimal.Underflow
3295 Clamped = self.decimal.Clamped
3296 Subnormal = self.decimal.Subnormal
3297 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
3298
3299 def raise_error(context, flag):
3300 if self.decimal == C:
3301 context.flags[flag] = True
3302 if context.traps[flag]:
3303 raise flag
3304 else:
3305 context._raise_error(flag)
3306
3307 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3308 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3309
3310 # operations that raise various flags, in the form (function, arglist)
3311 operations = [
3312 (context._apply, [Decimal("100E-425000010")]),
3313 (context.sqrt, [Decimal(2)]),
3314 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3315 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3316 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3317 ]
3318
3319 # try various flags individually, then a whole lot at once
3320 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3321 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3322
3323 for fn, args in operations:
3324 # find answer and flags raised using a clean context
3325 context.clear_flags()
3326 ans = fn(*args)
3327 flags = [k for k, v in context.flags.items() if v]
3328
3329 for extra_flags in flagsets:
3330 # set flags, before calling operation
3331 context.clear_flags()
3332 for flag in extra_flags:
3333 raise_error(context, flag)
3334 new_ans = fn(*args)
3335
3336 # flags that we expect to be set after the operation
3337 expected_flags = list(flags)
3338 for flag in extra_flags:
3339 if flag not in expected_flags:
3340 expected_flags.append(flag)
3341 expected_flags.sort(key=id)
3342
3343 # flags we actually got
3344 new_flags = [k for k,v in context.flags.items() if v]
3345 new_flags.sort(key=id)
3346
3347 self.assertEqual(ans, new_ans,
3348 "operation produces different answers depending on flags set: " +
3349 "expected %s, got %s." % (ans, new_ans))
3350 self.assertEqual(new_flags, expected_flags,
3351 "operation raises different flags depending on flags set: " +
3352 "expected %s, got %s" % (expected_flags, new_flags))
3353
3354 def test_flag_comparisons(self):
3355 Context = self.decimal.Context
3356 Inexact = self.decimal.Inexact
3357 Rounded = self.decimal.Rounded
3358
3359 c = Context()
3360
3361 # Valid SignalDict
3362 self.assertNotEqual(c.flags, c.traps)
3363 self.assertNotEqual(c.traps, c.flags)
3364
3365 c.flags = c.traps
3366 self.assertEqual(c.flags, c.traps)
3367 self.assertEqual(c.traps, c.flags)
3368
3369 c.flags[Rounded] = True
3370 c.traps = c.flags
3371 self.assertEqual(c.flags, c.traps)
3372 self.assertEqual(c.traps, c.flags)
3373
3374 d = {}
3375 d.update(c.flags)
3376 self.assertEqual(d, c.flags)
3377 self.assertEqual(c.flags, d)
3378
3379 d[Inexact] = True
3380 self.assertNotEqual(d, c.flags)
3381 self.assertNotEqual(c.flags, d)
3382
3383 # Invalid SignalDict
3384 d = {Inexact:False}
3385 self.assertNotEqual(d, c.flags)
3386 self.assertNotEqual(c.flags, d)
3387
3388 d = ["xyz"]
3389 self.assertNotEqual(d, c.flags)
3390 self.assertNotEqual(c.flags, d)
3391
3392 @requires_IEEE_754
3393 def test_float_operation(self):
3394 Decimal = self.decimal.Decimal
3395 FloatOperation = self.decimal.FloatOperation
3396 localcontext = self.decimal.localcontext
3397
3398 with localcontext() as c:
3399 ##### trap is off by default
3400 self.assertFalse(c.traps[FloatOperation])
3401
3402 # implicit conversion sets the flag
3403 c.clear_flags()
3404 self.assertEqual(Decimal(7.5), 7.5)
3405 self.assertTrue(c.flags[FloatOperation])
3406
3407 c.clear_flags()
3408 self.assertEqual(c.create_decimal(7.5), 7.5)
3409 self.assertTrue(c.flags[FloatOperation])
3410
3411 # explicit conversion does not set the flag
3412 c.clear_flags()
3413 x = Decimal.from_float(7.5)
3414 self.assertFalse(c.flags[FloatOperation])
3415 # comparison sets the flag
3416 self.assertEqual(x, 7.5)
3417 self.assertTrue(c.flags[FloatOperation])
3418
3419 c.clear_flags()
3420 x = c.create_decimal_from_float(7.5)
3421 self.assertFalse(c.flags[FloatOperation])
3422 self.assertEqual(x, 7.5)
3423 self.assertTrue(c.flags[FloatOperation])
3424
3425 ##### set the trap
3426 c.traps[FloatOperation] = True
3427
3428 # implicit conversion raises
3429 c.clear_flags()
3430 self.assertRaises(FloatOperation, Decimal, 7.5)
3431 self.assertTrue(c.flags[FloatOperation])
3432
3433 c.clear_flags()
3434 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3435 self.assertTrue(c.flags[FloatOperation])
3436
3437 # explicit conversion is silent
3438 c.clear_flags()
3439 x = Decimal.from_float(7.5)
3440 self.assertFalse(c.flags[FloatOperation])
3441
3442 c.clear_flags()
3443 x = c.create_decimal_from_float(7.5)
3444 self.assertFalse(c.flags[FloatOperation])
3445
3446 def test_float_comparison(self):
3447 Decimal = self.decimal.Decimal
3448 Context = self.decimal.Context
3449 FloatOperation = self.decimal.FloatOperation
3450 localcontext = self.decimal.localcontext
3451
3452 def assert_attr(a, b, attr, context, signal=None):
3453 context.clear_flags()
3454 f = getattr(a, attr)
3455 if signal == FloatOperation:
3456 self.assertRaises(signal, f, b)
3457 else:
3458 self.assertIs(f(b), True)
3459 self.assertTrue(context.flags[FloatOperation])
3460
3461 small_d = Decimal('0.25')
3462 big_d = Decimal('3.0')
3463 small_f = 0.25
3464 big_f = 3.0
3465
3466 zero_d = Decimal('0.0')
3467 neg_zero_d = Decimal('-0.0')
3468 zero_f = 0.0
3469 neg_zero_f = -0.0
3470
3471 inf_d = Decimal('Infinity')
3472 neg_inf_d = Decimal('-Infinity')
3473 inf_f = float('inf')
3474 neg_inf_f = float('-inf')
3475
3476 def doit(c, signal=None):
3477 # Order
3478 for attr in '__lt__', '__le__':
3479 assert_attr(small_d, big_f, attr, c, signal)
3480
3481 for attr in '__gt__', '__ge__':
3482 assert_attr(big_d, small_f, attr, c, signal)
3483
3484 # Equality
3485 assert_attr(small_d, small_f, '__eq__', c, None)
3486
3487 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3488 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3489
3490 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3491 assert_attr(zero_d, zero_f, '__eq__', c, None)
3492
3493 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3494 assert_attr(inf_d, inf_f, '__eq__', c, None)
3495
3496 # Inequality
3497 assert_attr(small_d, big_f, '__ne__', c, None)
3498
3499 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3500
3501 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3502 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3503
3504 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3505
3506 def test_containers(c, signal=None):
3507 c.clear_flags()
3508 s = set([100.0, Decimal('100.0')])
3509 self.assertEqual(len(s), 1)
3510 self.assertTrue(c.flags[FloatOperation])
3511
3512 c.clear_flags()
3513 if signal:
3514 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3515 else:
3516 s = sorted([10.0, Decimal('10.0')])
3517 self.assertTrue(c.flags[FloatOperation])
3518
3519 c.clear_flags()
3520 b = 10.0 in [Decimal('10.0'), 1.0]
3521 self.assertTrue(c.flags[FloatOperation])
3522
3523 c.clear_flags()
3524 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3525 self.assertTrue(c.flags[FloatOperation])
3526
3527 nc = Context()
3528 with localcontext(nc) as c:
3529 self.assertFalse(c.traps[FloatOperation])
3530 doit(c, signal=None)
3531 test_containers(c, signal=None)
3532
3533 c.traps[FloatOperation] = True
3534 doit(c, signal=FloatOperation)
3535 test_containers(c, signal=FloatOperation)
3536
3537 def test_float_operation_default(self):
3538 Decimal = self.decimal.Decimal
3539 Context = self.decimal.Context
3540 Inexact = self.decimal.Inexact
3541 FloatOperation= self.decimal.FloatOperation
3542
3543 context = Context()
3544 self.assertFalse(context.flags[FloatOperation])
3545 self.assertFalse(context.traps[FloatOperation])
3546
3547 context.clear_traps()
3548 context.traps[Inexact] = True
3549 context.traps[FloatOperation] = True
3550 self.assertTrue(context.traps[FloatOperation])
3551 self.assertTrue(context.traps[Inexact])
3552
3553class CContextFlags(ContextFlags):
3554 decimal = C
3555class PyContextFlags(ContextFlags):
3556 decimal = P
3557
3558class SpecialContexts(unittest.TestCase):
3559 """Test the context templates."""
3560
3561 def test_context_templates(self):
3562 BasicContext = self.decimal.BasicContext
3563 ExtendedContext = self.decimal.ExtendedContext
3564 getcontext = self.decimal.getcontext
3565 setcontext = self.decimal.setcontext
3566 InvalidOperation = self.decimal.InvalidOperation
3567 DivisionByZero = self.decimal.DivisionByZero
3568 Overflow = self.decimal.Overflow
3569 Underflow = self.decimal.Underflow
3570 Clamped = self.decimal.Clamped
3571
3572 assert_signals(self, BasicContext, 'traps',
3573 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3574 )
3575
3576 savecontext = getcontext().copy()
3577 basic_context_prec = BasicContext.prec
3578 extended_context_prec = ExtendedContext.prec
3579
3580 ex = None
3581 try:
3582 BasicContext.prec = ExtendedContext.prec = 441
3583 for template in BasicContext, ExtendedContext:
3584 setcontext(template)
3585 c = getcontext()
3586 self.assertIsNot(c, template)
3587 self.assertEqual(c.prec, 441)
3588 except Exception as e:
3589 ex = e.__class__
3590 finally:
3591 BasicContext.prec = basic_context_prec
3592 ExtendedContext.prec = extended_context_prec
3593 setcontext(savecontext)
3594 if ex:
3595 raise ex
3596
3597 def test_default_context(self):
3598 DefaultContext = self.decimal.DefaultContext
3599 BasicContext = self.decimal.BasicContext
3600 ExtendedContext = self.decimal.ExtendedContext
3601 getcontext = self.decimal.getcontext
3602 setcontext = self.decimal.setcontext
3603 InvalidOperation = self.decimal.InvalidOperation
3604 DivisionByZero = self.decimal.DivisionByZero
3605 Overflow = self.decimal.Overflow
3606
3607 self.assertEqual(BasicContext.prec, 9)
3608 self.assertEqual(ExtendedContext.prec, 9)
3609
3610 assert_signals(self, DefaultContext, 'traps',
3611 [InvalidOperation, DivisionByZero, Overflow]
3612 )
3613
3614 savecontext = getcontext().copy()
3615 default_context_prec = DefaultContext.prec
3616
3617 ex = None
3618 try:
3619 c = getcontext()
3620 saveprec = c.prec
3621
3622 DefaultContext.prec = 961
3623 c = getcontext()
3624 self.assertEqual(c.prec, saveprec)
3625
3626 setcontext(DefaultContext)
3627 c = getcontext()
3628 self.assertIsNot(c, DefaultContext)
3629 self.assertEqual(c.prec, 961)
3630 except Exception as e:
3631 ex = e.__class__
3632 finally:
3633 DefaultContext.prec = default_context_prec
3634 setcontext(savecontext)
3635 if ex:
3636 raise ex
3637
3638class CSpecialContexts(SpecialContexts):
3639 decimal = C
3640class PySpecialContexts(SpecialContexts):
3641 decimal = P
3642
3643class ContextInputValidation(unittest.TestCase):
3644
3645 def test_invalid_context(self):
3646 Context = self.decimal.Context
3647 DefaultContext = self.decimal.DefaultContext
3648
3649 c = DefaultContext.copy()
3650
3651 # prec, Emax
3652 for attr in ['prec', 'Emax']:
3653 setattr(c, attr, 999999)
3654 self.assertEqual(getattr(c, attr), 999999)
3655 self.assertRaises(ValueError, setattr, c, attr, -1)
3656 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3657
3658 # Emin
3659 setattr(c, 'Emin', -999999)
3660 self.assertEqual(getattr(c, 'Emin'), -999999)
3661 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3662 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3663
3664 # rounding: always raise TypeError in order to get consistent
3665 # exceptions across implementations. In decimal, rounding
3666 # modes are strings, in _decimal they are integers. The idea
3667 # is to view rounding as an abstract type and not mind the
3668 # implementation details.
3669 # Hence, a user should view the rounding modes as if they
3670 # had been defined in a language that supports abstract
3671 # data types, e.g. ocaml:
3672 #
3673 # type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;;
3674 #
3675 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3676 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3677 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3678 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3679
3680 # capitals, clamp
3681 for attr in ['capitals', 'clamp']:
3682 self.assertRaises(ValueError, setattr, c, attr, -1)
3683 self.assertRaises(ValueError, setattr, c, attr, 2)
3684 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3685
3686 # Invalid attribute
3687 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3688
3689 # Invalid signal dict
3690 self.assertRaises(TypeError, setattr, c, 'flags', [])
3691 self.assertRaises(KeyError, setattr, c, 'flags', {})
3692 self.assertRaises(KeyError, setattr, c, 'traps',
3693 {'InvalidOperation':0})
3694
3695 # Attributes cannot be deleted
3696 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3697 'flags', 'traps']:
3698 self.assertRaises(AttributeError, c.__delattr__, attr)
3699
3700 # Invalid attributes
3701 self.assertRaises(TypeError, getattr, c, 9)
3702 self.assertRaises(TypeError, setattr, c, 9)
3703
3704 # Invalid values in constructor
3705 self.assertRaises(TypeError, Context, rounding=999999)
3706 self.assertRaises(TypeError, Context, rounding='xyz')
3707 self.assertRaises(ValueError, Context, clamp=2)
3708 self.assertRaises(ValueError, Context, capitals=-1)
3709 self.assertRaises(KeyError, Context, flags=["P"])
3710 self.assertRaises(KeyError, Context, traps=["Q"])
3711
3712 # Type error in conversion
3713 self.assertRaises(TypeError, Context, flags=(0,1))
3714 self.assertRaises(TypeError, Context, traps=(1,0))
3715
3716class CContextInputValidation(ContextInputValidation):
3717 decimal = C
3718class PyContextInputValidation(ContextInputValidation):
3719 decimal = P
3720
3721class ContextSubclassing(unittest.TestCase):
3722
3723 def test_context_subclassing(self):
3724 decimal = self.decimal
3725 Decimal = decimal.Decimal
3726 Context = decimal.Context
3727 ROUND_HALF_EVEN = decimal.ROUND_HALF_EVEN
3728 ROUND_DOWN = decimal.ROUND_DOWN
3729 Clamped = decimal.Clamped
3730 DivisionByZero = decimal.DivisionByZero
3731 Inexact = decimal.Inexact
3732 Overflow = decimal.Overflow
3733 Rounded = decimal.Rounded
3734 Subnormal = decimal.Subnormal
3735 Underflow = decimal.Underflow
3736 InvalidOperation = decimal.InvalidOperation
3737
3738 class MyContext(Context):
3739 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
3740 capitals=None, clamp=None, flags=None,
3741 traps=None):
3742 Context.__init__(self)
3743 if prec is not None:
3744 self.prec = prec
3745 if rounding is not None:
3746 self.rounding = rounding
3747 if Emin is not None:
3748 self.Emin = Emin
3749 if Emax is not None:
3750 self.Emax = Emax
3751 if capitals is not None:
3752 self.capitals = capitals
3753 if clamp is not None:
3754 self.clamp = clamp
3755 if flags is not None:
3756 if isinstance(flags, list):
3757 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
3758 self.flags = flags
3759 if traps is not None:
3760 if isinstance(traps, list):
3761 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
3762 self.traps = traps
3763
3764 c = Context()
3765 d = MyContext()
3766 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
3767 'flags', 'traps'):
3768 self.assertEqual(getattr(c, attr), getattr(d, attr))
3769
3770 # prec
3771 self.assertRaises(ValueError, MyContext, **{'prec':-1})
3772 c = MyContext(prec=1)
3773 self.assertEqual(c.prec, 1)
3774 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
3775
3776 # rounding
3777 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
3778 c = MyContext(rounding=ROUND_DOWN, prec=1)
3779 self.assertEqual(c.rounding, ROUND_DOWN)
3780 self.assertEqual(c.plus(Decimal('9.9')), 9)
3781
3782 # Emin
3783 self.assertRaises(ValueError, MyContext, **{'Emin':5})
3784 c = MyContext(Emin=-1, prec=1)
3785 self.assertEqual(c.Emin, -1)
3786 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
3787 self.assertEqual(x, Decimal('0.0'))
3788 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
3789 self.assertTrue(c.flags[signal])
3790
3791 # Emax
3792 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
3793 c = MyContext(Emax=1, prec=1)
3794 self.assertEqual(c.Emax, 1)
3795 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
3796 if self.decimal == C:
3797 for signal in (Inexact, Overflow, Rounded):
3798 self.assertTrue(c.flags[signal])
3799
3800 # capitals
3801 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
3802 c = MyContext(capitals=0)
3803 self.assertEqual(c.capitals, 0)
3804 x = c.create_decimal('1E222')
3805 self.assertEqual(c.to_sci_string(x), '1e+222')
3806
3807 # clamp
3808 self.assertRaises(ValueError, MyContext, **{'clamp':2})
3809 c = MyContext(clamp=1, Emax=99)
3810 self.assertEqual(c.clamp, 1)
3811 x = c.plus(Decimal('1e99'))
3812 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
3813
3814 # flags
3815 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
3816 c = MyContext(flags=[Rounded, DivisionByZero])
3817 for signal in (Rounded, DivisionByZero):
3818 self.assertTrue(c.flags[signal])
3819 c.clear_flags()
3820 for signal in OrderedSignals[decimal]:
3821 self.assertFalse(c.flags[signal])
3822
3823 # traps
3824 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
3825 c = MyContext(traps=[Rounded, DivisionByZero])
3826 for signal in (Rounded, DivisionByZero):
3827 self.assertTrue(c.traps[signal])
3828 c.clear_traps()
3829 for signal in OrderedSignals[decimal]:
3830 self.assertFalse(c.traps[signal])
3831
3832class CContextSubclassing(ContextSubclassing):
3833 decimal = C
3834class PyContextSubclassing(ContextSubclassing):
3835 decimal = P
3836
3837@skip_if_extra_functionality
3838class CheckAttributes(unittest.TestCase):
3839
3840 def test_module_attributes(self):
3841
3842 # Architecture dependent context limits
3843 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
3844 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
3845 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
3846 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
3847
3848 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
3849 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
3850
3851 self.assertEqual(C.__version__, P.__version__)
3852
3853 x = dir(C)
3854 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02003855 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01003856
3857 def test_context_attributes(self):
3858
3859 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
3860 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
3861 self.assertEqual(set(x) - set(y), set())
3862
3863 def test_decimal_attributes(self):
3864
3865 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3866 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3867 self.assertEqual(set(x) - set(y), set())
3868
3869class Coverage(unittest.TestCase):
3870
3871 def test_adjusted(self):
3872 Decimal = self.decimal.Decimal
3873
3874 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
3875 # XXX raise?
3876 self.assertEqual(Decimal('nan').adjusted(), 0)
3877 self.assertEqual(Decimal('inf').adjusted(), 0)
3878
3879 def test_canonical(self):
3880 Decimal = self.decimal.Decimal
3881 getcontext = self.decimal.getcontext
3882
3883 x = Decimal(9).canonical()
3884 self.assertEqual(x, 9)
3885
3886 c = getcontext()
3887 x = c.canonical(Decimal(9))
3888 self.assertEqual(x, 9)
3889
3890 def test_context_repr(self):
3891 c = self.decimal.DefaultContext.copy()
3892
3893 c.prec = 425000000
3894 c.Emax = 425000000
3895 c.Emin = -425000000
3896 c.rounding = self.decimal.ROUND_HALF_DOWN
3897 c.capitals = 0
3898 c.clamp = 1
3899 for sig in OrderedSignals[self.decimal]:
3900 c.flags[sig] = False
3901 c.traps[sig] = False
3902
3903 s = c.__repr__()
3904 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
3905 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
3906 "flags=[], traps=[])"
3907 self.assertEqual(s, t)
3908
3909 def test_implicit_context(self):
3910 Decimal = self.decimal.Decimal
3911 localcontext = self.decimal.localcontext
3912
3913 with localcontext() as c:
3914 c.prec = 1
3915 c.Emax = 1
3916 c.Emin = -1
3917
3918 # abs
3919 self.assertEqual(abs(Decimal("-10")), 10)
3920 # add
3921 self.assertEqual(Decimal("7") + 1, 8)
3922 # divide
3923 self.assertEqual(Decimal("10") / 5, 2)
3924 # divide_int
3925 self.assertEqual(Decimal("10") // 7, 1)
3926 # fma
3927 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
3928 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
3929 # three arg power
3930 self.assertEqual(pow(Decimal(10), 2, 7), 2)
3931 # exp
3932 self.assertEqual(Decimal("1.01").exp(), 3)
3933 # is_normal
3934 self.assertIs(Decimal("0.01").is_normal(), False)
3935 # is_subnormal
3936 self.assertIs(Decimal("0.01").is_subnormal(), True)
3937 # ln
3938 self.assertEqual(Decimal("20").ln(), 3)
3939 # log10
3940 self.assertEqual(Decimal("20").log10(), 1)
3941 # logb
3942 self.assertEqual(Decimal("580").logb(), 2)
3943 # logical_invert
3944 self.assertEqual(Decimal("10").logical_invert(), 1)
3945 # minus
3946 self.assertEqual(-Decimal("-10"), 10)
3947 # multiply
3948 self.assertEqual(Decimal("2") * 4, 8)
3949 # next_minus
3950 self.assertEqual(Decimal("10").next_minus(), 9)
3951 # next_plus
3952 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
3953 # normalize
3954 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
3955 # number_class
3956 self.assertEqual(Decimal("10").number_class(), '+Normal')
3957 # plus
3958 self.assertEqual(+Decimal("-1"), -1)
3959 # remainder
3960 self.assertEqual(Decimal("10") % 7, 3)
3961 # subtract
3962 self.assertEqual(Decimal("10") - 7, 3)
3963 # to_integral_exact
3964 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
3965
3966 # Boolean functions
3967 self.assertTrue(Decimal("1").is_canonical())
3968 self.assertTrue(Decimal("1").is_finite())
3969 self.assertTrue(Decimal("1").is_finite())
3970 self.assertTrue(Decimal("snan").is_snan())
3971 self.assertTrue(Decimal("-1").is_signed())
3972 self.assertTrue(Decimal("0").is_zero())
3973 self.assertTrue(Decimal("0").is_zero())
3974
3975 # Copy
3976 with localcontext() as c:
3977 c.prec = 10000
3978 x = 1228 ** 1523
3979 y = -Decimal(x)
3980
3981 z = y.copy_abs()
3982 self.assertEqual(z, x)
3983
3984 z = y.copy_negate()
3985 self.assertEqual(z, x)
3986
3987 z = y.copy_sign(Decimal(1))
3988 self.assertEqual(z, x)
3989
3990 def test_divmod(self):
3991 Decimal = self.decimal.Decimal
3992 localcontext = self.decimal.localcontext
3993 InvalidOperation = self.decimal.InvalidOperation
3994 DivisionByZero = self.decimal.DivisionByZero
3995
3996 with localcontext() as c:
3997 q, r = divmod(Decimal("10912837129"), 1001)
3998 self.assertEqual(q, Decimal('10901935'))
3999 self.assertEqual(r, Decimal('194'))
4000
4001 q, r = divmod(Decimal("NaN"), 7)
4002 self.assertTrue(q.is_nan() and r.is_nan())
4003
4004 c.traps[InvalidOperation] = False
4005 q, r = divmod(Decimal("NaN"), 7)
4006 self.assertTrue(q.is_nan() and r.is_nan())
4007
4008 c.traps[InvalidOperation] = False
4009 c.clear_flags()
4010 q, r = divmod(Decimal("inf"), Decimal("inf"))
4011 self.assertTrue(q.is_nan() and r.is_nan())
4012 self.assertTrue(c.flags[InvalidOperation])
4013
4014 c.clear_flags()
4015 q, r = divmod(Decimal("inf"), 101)
4016 self.assertTrue(q.is_infinite() and r.is_nan())
4017 self.assertTrue(c.flags[InvalidOperation])
4018
4019 c.clear_flags()
4020 q, r = divmod(Decimal(0), 0)
4021 self.assertTrue(q.is_nan() and r.is_nan())
4022 self.assertTrue(c.flags[InvalidOperation])
4023
4024 c.traps[DivisionByZero] = False
4025 c.clear_flags()
4026 q, r = divmod(Decimal(11), 0)
4027 self.assertTrue(q.is_infinite() and r.is_nan())
4028 self.assertTrue(c.flags[InvalidOperation] and
4029 c.flags[DivisionByZero])
4030
4031 def test_power(self):
4032 Decimal = self.decimal.Decimal
4033 localcontext = self.decimal.localcontext
4034 Overflow = self.decimal.Overflow
4035 Rounded = self.decimal.Rounded
4036
4037 with localcontext() as c:
4038 c.prec = 3
4039 c.clear_flags()
4040 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4041 self.assertTrue(c.flags[Rounded])
4042
4043 c.prec = 1
4044 c.Emax = 1
4045 c.Emin = -1
4046 c.clear_flags()
4047 c.traps[Overflow] = False
4048 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4049 self.assertTrue(c.flags[Overflow])
4050
4051 def test_quantize(self):
4052 Decimal = self.decimal.Decimal
4053 localcontext = self.decimal.localcontext
4054 InvalidOperation = self.decimal.InvalidOperation
4055
4056 with localcontext() as c:
4057 c.prec = 1
4058 c.Emax = 1
4059 c.Emin = -1
4060 c.traps[InvalidOperation] = False
4061 x = Decimal(99).quantize(Decimal("1e1"))
4062 self.assertTrue(x.is_nan())
4063
4064 def test_radix(self):
4065 Decimal = self.decimal.Decimal
4066 getcontext = self.decimal.getcontext
4067
4068 c = getcontext()
4069 self.assertEqual(Decimal("1").radix(), 10)
4070 self.assertEqual(c.radix(), 10)
4071
4072 def test_rop(self):
4073 Decimal = self.decimal.Decimal
4074
4075 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4076 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4077 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4078
4079 def test_round(self):
4080 # Python3 behavior: round() returns Decimal
4081 Decimal = self.decimal.Decimal
4082 getcontext = self.decimal.getcontext
4083
4084 c = getcontext()
4085 c.prec = 28
4086
4087 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4088 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4089 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4090 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4091 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4092
4093 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4094 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4095
4096 def test_create_decimal(self):
4097 c = self.decimal.Context()
4098 self.assertRaises(ValueError, c.create_decimal, ["%"])
4099
4100 def test_int(self):
4101 Decimal = self.decimal.Decimal
4102 localcontext = self.decimal.localcontext
4103
4104 with localcontext() as c:
4105 c.prec = 9999
4106 x = Decimal(1221**1271) / 10**3923
4107 self.assertEqual(int(x), 1)
4108 self.assertEqual(x.to_integral(), 2)
4109
4110 def test_copy(self):
4111 Context = self.decimal.Context
4112
4113 c = Context()
4114 c.prec = 10000
4115 x = -(1172 ** 1712)
4116
4117 y = c.copy_abs(x)
4118 self.assertEqual(y, -x)
4119
4120 y = c.copy_negate(x)
4121 self.assertEqual(y, -x)
4122
4123 y = c.copy_sign(x, 1)
4124 self.assertEqual(y, -x)
4125
4126class CCoverage(Coverage):
4127 decimal = C
4128class PyCoverage(Coverage):
4129 decimal = P
4130
4131class PyFunctionality(unittest.TestCase):
4132 """Extra functionality in decimal.py"""
4133
4134 def test_py_quantize_watchexp(self):
4135 # watchexp functionality
4136 Decimal = P.Decimal
4137 localcontext = P.localcontext
4138
4139 with localcontext() as c:
4140 c.prec = 1
4141 c.Emax = 1
4142 c.Emin = -1
4143 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4144 self.assertEqual(x, Decimal('1.00E+5'))
4145
4146 def test_py_alternate_formatting(self):
4147 # triples giving a format, a Decimal, and the expected result
4148 Decimal = P.Decimal
4149 localcontext = P.localcontext
4150
4151 test_values = [
4152 # Issue 7094: Alternate formatting (specified by #)
4153 ('.0e', '1.0', '1e+0'),
4154 ('#.0e', '1.0', '1.e+0'),
4155 ('.0f', '1.0', '1'),
4156 ('#.0f', '1.0', '1.'),
4157 ('g', '1.1', '1.1'),
4158 ('#g', '1.1', '1.1'),
4159 ('.0g', '1', '1'),
4160 ('#.0g', '1', '1.'),
4161 ('.0%', '1.0', '100%'),
4162 ('#.0%', '1.0', '100.%'),
4163 ]
4164 for fmt, d, result in test_values:
4165 self.assertEqual(format(Decimal(d), fmt), result)
4166
4167class PyWhitebox(unittest.TestCase):
4168 """White box testing for decimal.py"""
4169
4170 def test_py_exact_power(self):
4171 # Rarely exercised lines in _power_exact.
4172 Decimal = P.Decimal
4173 localcontext = P.localcontext
4174
4175 with localcontext() as c:
4176 c.prec = 8
4177 x = Decimal(2**16) ** Decimal("-0.5")
4178 self.assertEqual(x, Decimal('0.00390625'))
4179
4180 x = Decimal(2**16) ** Decimal("-0.6")
4181 self.assertEqual(x, Decimal('0.0012885819'))
4182
4183 x = Decimal("256e7") ** Decimal("-0.5")
4184
4185 x = Decimal(152587890625) ** Decimal('-0.0625')
4186 self.assertEqual(x, Decimal("0.2"))
4187
4188 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4189
4190 x = Decimal(5**2659) ** Decimal('-0.0625')
4191
4192 c.prec = 1
4193 x = Decimal("152587890625") ** Decimal('-0.5')
4194 c.prec = 201
4195 x = Decimal(2**578) ** Decimal("-0.5")
4196
4197 def test_py_immutability_operations(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004198 # Do operations and check that it didn't change change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004199 Decimal = P.Decimal
4200 DefaultContext = P.DefaultContext
4201 setcontext = P.setcontext
4202
4203 c = DefaultContext.copy()
4204 c.traps = dict((s, 0) for s in OrderedSignals[P])
4205 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004206
4207 d1 = Decimal('-25e55')
4208 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004209 d2 = Decimal('33e+33')
4210 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004211
4212 def checkSameDec(operation, useOther=False):
4213 if useOther:
4214 eval("d1." + operation + "(d2)")
4215 self.assertEqual(d1._sign, b1._sign)
4216 self.assertEqual(d1._int, b1._int)
4217 self.assertEqual(d1._exp, b1._exp)
4218 self.assertEqual(d2._sign, b2._sign)
4219 self.assertEqual(d2._int, b2._int)
4220 self.assertEqual(d2._exp, b2._exp)
4221 else:
4222 eval("d1." + operation + "()")
4223 self.assertEqual(d1._sign, b1._sign)
4224 self.assertEqual(d1._int, b1._int)
4225 self.assertEqual(d1._exp, b1._exp)
4226 return
4227
4228 Decimal(d1)
4229 self.assertEqual(d1._sign, b1._sign)
4230 self.assertEqual(d1._int, b1._int)
4231 self.assertEqual(d1._exp, b1._exp)
4232
4233 checkSameDec("__abs__")
4234 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004235 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004236 checkSameDec("__eq__", True)
4237 checkSameDec("__ne__", True)
4238 checkSameDec("__le__", True)
4239 checkSameDec("__lt__", True)
4240 checkSameDec("__ge__", True)
4241 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004242 checkSameDec("__float__")
4243 checkSameDec("__floordiv__", True)
4244 checkSameDec("__hash__")
4245 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004246 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004247 checkSameDec("__mod__", True)
4248 checkSameDec("__mul__", True)
4249 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004250 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004251 checkSameDec("__pos__")
4252 checkSameDec("__pow__", True)
4253 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004254 checkSameDec("__rdivmod__", True)
4255 checkSameDec("__repr__")
4256 checkSameDec("__rfloordiv__", True)
4257 checkSameDec("__rmod__", True)
4258 checkSameDec("__rmul__", True)
4259 checkSameDec("__rpow__", True)
4260 checkSameDec("__rsub__", True)
4261 checkSameDec("__str__")
4262 checkSameDec("__sub__", True)
4263 checkSameDec("__truediv__", True)
4264 checkSameDec("adjusted")
4265 checkSameDec("as_tuple")
4266 checkSameDec("compare", True)
4267 checkSameDec("max", True)
4268 checkSameDec("min", True)
4269 checkSameDec("normalize")
4270 checkSameDec("quantize", True)
4271 checkSameDec("remainder_near", True)
4272 checkSameDec("same_quantum", True)
4273 checkSameDec("sqrt")
4274 checkSameDec("to_eng_string")
4275 checkSameDec("to_integral")
4276
Stefan Krah1919b7e2012-03-21 18:25:23 +01004277 def test_py_decimal_id(self):
4278 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004279
Stefan Krah1919b7e2012-03-21 18:25:23 +01004280 d = Decimal(45)
4281 e = Decimal(d)
4282 self.assertEqual(str(e), '45')
4283 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004284
Stefan Krah1919b7e2012-03-21 18:25:23 +01004285 def test_py_rescale(self):
4286 # Coverage
4287 Decimal = P.Decimal
4288 ROUND_UP = P.ROUND_UP
4289 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004290
Stefan Krah1919b7e2012-03-21 18:25:23 +01004291 with localcontext() as c:
4292 x = Decimal("NaN")._rescale(3, ROUND_UP)
4293 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004294
Stefan Krah1919b7e2012-03-21 18:25:23 +01004295 def test_py__round(self):
4296 # Coverage
4297 Decimal = P.Decimal
4298 ROUND_UP = P.ROUND_UP
Christian Heimes0348fb62008-03-26 12:55:56 +00004299
Stefan Krah1919b7e2012-03-21 18:25:23 +01004300 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004301
Stefan Krah1919b7e2012-03-21 18:25:23 +01004302class CFunctionality(unittest.TestCase):
4303 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004304
Stefan Krah1919b7e2012-03-21 18:25:23 +01004305 @requires_extra_functionality
4306 def test_c_ieee_context(self):
4307 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4308 IEEEContext = C.IEEEContext
4309 DECIMAL32 = C.DECIMAL32
4310 DECIMAL64 = C.DECIMAL64
4311 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004312
Stefan Krah1919b7e2012-03-21 18:25:23 +01004313 def assert_rest(self, context):
4314 self.assertEqual(context.clamp, 1)
4315 assert_signals(self, context, 'traps', [])
4316 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004317
Stefan Krah1919b7e2012-03-21 18:25:23 +01004318 c = IEEEContext(DECIMAL32)
4319 self.assertEqual(c.prec, 7)
4320 self.assertEqual(c.Emax, 96)
4321 self.assertEqual(c.Emin, -95)
4322 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004323
Stefan Krah1919b7e2012-03-21 18:25:23 +01004324 c = IEEEContext(DECIMAL64)
4325 self.assertEqual(c.prec, 16)
4326 self.assertEqual(c.Emax, 384)
4327 self.assertEqual(c.Emin, -383)
4328 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004329
Stefan Krah1919b7e2012-03-21 18:25:23 +01004330 c = IEEEContext(DECIMAL128)
4331 self.assertEqual(c.prec, 34)
4332 self.assertEqual(c.Emax, 6144)
4333 self.assertEqual(c.Emin, -6143)
4334 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004335
Stefan Krah1919b7e2012-03-21 18:25:23 +01004336 # Invalid values
4337 self.assertRaises(OverflowError, IEEEContext, 2**63)
4338 self.assertRaises(ValueError, IEEEContext, -1)
4339 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004340
Stefan Krah1919b7e2012-03-21 18:25:23 +01004341 @requires_extra_functionality
4342 def test_c_context(self):
4343 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004344
Stefan Krah1919b7e2012-03-21 18:25:23 +01004345 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4346 self.assertEqual(c._flags, C.DecClamped)
4347 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004348
Stefan Krah1919b7e2012-03-21 18:25:23 +01004349 @requires_extra_functionality
4350 def test_constants(self):
4351 # Condition flags
4352 cond = (
4353 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4354 C.DecDivisionImpossible, C.DecDivisionUndefined,
4355 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4356 C.DecInvalidOperation, C.DecMallocError,
4357 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4358 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004359 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004360
4361 # IEEEContext
4362 self.assertEqual(C.DECIMAL32, 32)
4363 self.assertEqual(C.DECIMAL64, 64)
4364 self.assertEqual(C.DECIMAL128, 128)
4365 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4366
4367 # Rounding modes
4368 for i, v in enumerate(RoundingModes[C]):
4369 self.assertEqual(v, i)
4370 self.assertEqual(C.ROUND_TRUNC, 8)
4371
4372 # Conditions
4373 for i, v in enumerate(cond):
4374 self.assertEqual(v, 1<<i)
4375
4376 self.assertEqual(C.DecIEEEInvalidOperation,
4377 C.DecConversionSyntax|
4378 C.DecDivisionImpossible|
4379 C.DecDivisionUndefined|
4380 C.DecFpuError|
4381 C.DecInvalidContext|
4382 C.DecInvalidOperation|
4383 C.DecMallocError)
4384
4385 self.assertEqual(C.DecErrors,
4386 C.DecIEEEInvalidOperation|
4387 C.DecDivisionByZero)
4388
4389 self.assertEqual(C.DecTraps,
4390 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4391
4392class CWhitebox(unittest.TestCase):
4393 """Whitebox testing for _decimal"""
4394
4395 def test_bignum(self):
4396 # Not exactly whitebox, but too slow with pydecimal.
4397
4398 Decimal = C.Decimal
4399 localcontext = C.localcontext
4400
4401 b1 = 10**35
4402 b2 = 10**36
4403 with localcontext() as c:
4404 c.prec = 1000000
4405 for i in range(5):
4406 a = random.randrange(b1, b2)
4407 b = random.randrange(1000, 1200)
4408 x = a ** b
4409 y = Decimal(a) ** Decimal(b)
4410 self.assertEqual(x, y)
4411
4412 def test_invalid_construction(self):
4413 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4414
4415 def test_c_input_restriction(self):
4416 # Too large for _decimal to be converted exactly
4417 Decimal = C.Decimal
4418 InvalidOperation = C.InvalidOperation
4419 Context = C.Context
4420 localcontext = C.localcontext
4421
4422 with localcontext(Context()):
4423 self.assertRaises(InvalidOperation, Decimal,
4424 "1e9999999999999999999")
4425
4426 def test_c_context_repr(self):
4427 # This test is _decimal-only because flags are not printed
4428 # in the same order.
4429 DefaultContext = C.DefaultContext
4430 FloatOperation = C.FloatOperation
4431 ROUND_HALF_DOWN = C.ROUND_HALF_DOWN
4432
4433 c = DefaultContext.copy()
4434
4435 c.prec = 425000000
4436 c.Emax = 425000000
4437 c.Emin = -425000000
4438 c.rounding = ROUND_HALF_DOWN
4439 c.capitals = 0
4440 c.clamp = 1
4441 for sig in OrderedSignals[C]:
4442 c.flags[sig] = True
4443 c.traps[sig] = True
4444 c.flags[FloatOperation] = True
4445 c.traps[FloatOperation] = True
4446
4447 s = c.__repr__()
4448 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4449 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4450 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4451 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4452 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4453 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4454 self.assertEqual(s, t)
4455
4456 def test_c_context_errors(self):
4457 Context = C.Context
4458 InvalidOperation = C.InvalidOperation
4459 Overflow = C.Overflow
4460 FloatOperation = C.FloatOperation
4461 localcontext = C.localcontext
4462 getcontext = C.getcontext
4463 setcontext = C.setcontext
4464 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4465
4466 c = Context()
4467
4468 # SignalDict: input validation
4469 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4470 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4471 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4472 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4473 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4474 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4475 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4476 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4477
4478 # Test assignment from a signal dict with the correct length but
4479 # one invalid key.
4480 d = c.flags.copy()
4481 del d[FloatOperation]
4482 d["XYZ"] = 91283719
4483 self.assertRaises(KeyError, setattr, c, 'flags', d)
4484 self.assertRaises(KeyError, setattr, c, 'traps', d)
4485
4486 # Input corner cases
4487 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4488 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4489
4490 # prec, Emax, Emin
4491 for attr in ['prec', 'Emax']:
4492 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4493 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4494
4495 # prec, Emax, Emin in context constructor
4496 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4497 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4498 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4499
4500 # Overflow in conversion
4501 self.assertRaises(OverflowError, Context, prec=int_max+1)
4502 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4503 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
4504 self.assertRaises(OverflowError, Context, rounding=int_max+1)
4505 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4506 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4507
4508 # OverflowError, general ValueError
4509 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4510 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4511 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4512 if sys.platform != 'win32':
4513 self.assertRaises(ValueError, setattr, c, attr, int_max)
4514 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4515
4516 # OverflowError, general TypeError
4517 for attr in ('rounding',):
4518 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4519 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4520 if sys.platform != 'win32':
4521 self.assertRaises(TypeError, setattr, c, attr, int_max)
4522 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4523
4524 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4525 if C.MAX_PREC == 425000000:
4526 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4527 int_max+1)
4528 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4529 int_max+1)
4530 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4531 -int_max-2)
4532
4533 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4534 if C.MAX_PREC == 425000000:
4535 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4536 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4537 1070000001)
4538 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4539 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4540 1070000001)
4541 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4542 -1070000001)
4543 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4544
4545 # capitals, clamp
4546 for attr in ['capitals', 'clamp']:
4547 self.assertRaises(ValueError, setattr, c, attr, -1)
4548 self.assertRaises(ValueError, setattr, c, attr, 2)
4549 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4550 if HAVE_CONFIG_64:
4551 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4552 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4553
4554 # Invalid local context
4555 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4556 locals())
4557
4558 # setcontext
4559 saved_context = getcontext()
4560 self.assertRaises(TypeError, setcontext, "xyz")
4561 setcontext(saved_context)
4562
4563 @requires_extra_functionality
4564 def test_c_context_errors_extra(self):
4565 Context = C.Context
4566 InvalidOperation = C.InvalidOperation
4567 Overflow = C.Overflow
4568 localcontext = C.localcontext
4569 getcontext = C.getcontext
4570 setcontext = C.setcontext
4571 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4572
4573 c = Context()
4574
4575 # Input corner cases
4576 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4577
4578 # OverflowError, general ValueError
4579 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4580 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4581 if sys.platform != 'win32':
4582 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4583 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4584
4585 # OverflowError, general TypeError
4586 for attr in ('_flags', '_traps'):
4587 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4588 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4589 if sys.platform != 'win32':
4590 self.assertRaises(TypeError, setattr, c, attr, int_max)
4591 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4592
4593 # _allcr
4594 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4595 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4596 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4597 if HAVE_CONFIG_64:
4598 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4599 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4600
4601 # _flags, _traps
4602 for attr in ['_flags', '_traps']:
4603 self.assertRaises(TypeError, setattr, c, attr, 999999)
4604 self.assertRaises(TypeError, setattr, c, attr, 'x')
4605
4606 def test_c_valid_context(self):
4607 # These tests are for code coverage in _decimal.
4608 DefaultContext = C.DefaultContext
4609 ROUND_HALF_UP = C.ROUND_HALF_UP
4610 Clamped = C.Clamped
4611 Underflow = C.Underflow
4612 Inexact = C.Inexact
4613 Rounded = C.Rounded
4614 Subnormal = C.Subnormal
4615
4616 c = DefaultContext.copy()
4617
4618 # Exercise all getters and setters
4619 c.prec = 34
4620 c.rounding = ROUND_HALF_UP
4621 c.Emax = 3000
4622 c.Emin = -3000
4623 c.capitals = 1
4624 c.clamp = 0
4625
4626 self.assertEqual(c.prec, 34)
4627 self.assertEqual(c.rounding, ROUND_HALF_UP)
4628 self.assertEqual(c.Emin, -3000)
4629 self.assertEqual(c.Emax, 3000)
4630 self.assertEqual(c.capitals, 1)
4631 self.assertEqual(c.clamp, 0)
4632
4633 self.assertEqual(c.Etiny(), -3033)
4634 self.assertEqual(c.Etop(), 2967)
4635
4636 # Exercise all unsafe setters
4637 if C.MAX_PREC == 425000000:
4638 c._unsafe_setprec(999999999)
4639 c._unsafe_setemax(999999999)
4640 c._unsafe_setemin(-999999999)
4641 self.assertEqual(c.prec, 999999999)
4642 self.assertEqual(c.Emax, 999999999)
4643 self.assertEqual(c.Emin, -999999999)
4644
4645 @requires_extra_functionality
4646 def test_c_valid_context_extra(self):
4647 DefaultContext = C.DefaultContext
4648
4649 c = DefaultContext.copy()
4650 self.assertEqual(c._allcr, 1)
4651 c._allcr = 0
4652 self.assertEqual(c._allcr, 0)
4653
4654 def test_c_round(self):
4655 # Restricted input.
4656 Decimal = C.Decimal
4657 InvalidOperation = C.InvalidOperation
4658 localcontext = C.localcontext
4659 MAX_EMAX = C.MAX_EMAX
4660 MIN_ETINY = C.MIN_ETINY
4661 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4662
4663 with localcontext() as c:
4664 c.traps[InvalidOperation] = True
4665 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4666 -int_max-1)
4667 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4668 int_max)
4669 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4670 int(MAX_EMAX+1))
4671 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4672 -int(MIN_ETINY-1))
4673 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4674 -int_max-2)
4675 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4676 int_max+1)
4677
4678 def test_c_format(self):
4679 # Restricted input
4680 Decimal = C.Decimal
4681 InvalidOperation = C.InvalidOperation
4682 Rounded = C.Rounded
4683 localcontext = C.localcontext
4684 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4685
4686 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4687 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4688 self.assertRaises(TypeError, Decimal(1).__format__, [])
4689
4690 with localcontext() as c:
4691 c.traps[InvalidOperation] = True
4692 c.traps[Rounded] = True
4693 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4694 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4695 self.assertRaises(InvalidOperation, Decimal("1.23456789").__format__,
4696 "=%d.1" % maxsize)
4697
4698 def test_c_integral(self):
4699 Decimal = C.Decimal
4700 Inexact = C.Inexact
4701 ROUND_UP = C.ROUND_UP
4702 localcontext = C.localcontext
4703
4704 x = Decimal(10)
4705 self.assertEqual(x.to_integral(), 10)
4706 self.assertRaises(TypeError, x.to_integral, '10')
4707 self.assertRaises(TypeError, x.to_integral, 10, 'x')
4708 self.assertRaises(TypeError, x.to_integral, 10)
4709
4710 self.assertEqual(x.to_integral_value(), 10)
4711 self.assertRaises(TypeError, x.to_integral_value, '10')
4712 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
4713 self.assertRaises(TypeError, x.to_integral_value, 10)
4714
4715 self.assertEqual(x.to_integral_exact(), 10)
4716 self.assertRaises(TypeError, x.to_integral_exact, '10')
4717 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
4718 self.assertRaises(TypeError, x.to_integral_exact, 10)
4719
4720 with localcontext() as c:
4721 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
4722 self.assertEqual(x, Decimal('100000000000000000000000000'))
4723
4724 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
4725 self.assertEqual(x, Decimal('100000000000000000000000000'))
4726
4727 c.traps[Inexact] = True
4728 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
4729
4730 def test_c_funcs(self):
4731 # Invalid arguments
4732 Decimal = C.Decimal
4733 InvalidOperation = C.InvalidOperation
4734 DivisionByZero = C.DivisionByZero
4735 ROUND_UP = C.ROUND_UP
4736 getcontext = C.getcontext
4737 localcontext = C.localcontext
4738
4739 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
4740
4741 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
4742 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
4743 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
4744
Raymond Hettinger771ed762009-01-03 19:20:32 +00004745 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01004746 TypeError,
4747 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00004748 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004749 self.assertRaises(
4750 TypeError,
4751 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
4752 )
4753 self.assertRaises(
4754 TypeError,
4755 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
4756 )
4757 self.assertRaises(
4758 TypeError,
4759 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
4760 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00004761
Stefan Krah1919b7e2012-03-21 18:25:23 +01004762 with localcontext() as c:
4763 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004764
Stefan Krah1919b7e2012-03-21 18:25:23 +01004765 # Invalid arguments
4766 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
4767 self.assertRaises(TypeError, c.canonical, 200)
4768 self.assertRaises(TypeError, c.is_canonical, 200)
4769 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
4770 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004771
Stefan Krah1919b7e2012-03-21 18:25:23 +01004772 self.assertEqual(str(c.canonical(Decimal(200))), '200')
4773 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00004774
Stefan Krah1919b7e2012-03-21 18:25:23 +01004775 c.traps[DivisionByZero] = True
4776 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
4777 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
4778 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00004779
Stefan Krah1919b7e2012-03-21 18:25:23 +01004780 c.clear_flags()
4781 c.traps[InvalidOperation] = True
4782 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
4783 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
4784 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00004785
Stefan Krah1919b7e2012-03-21 18:25:23 +01004786 c.traps[InvalidOperation] = True
4787 c.prec = 2
4788 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00004789
Stefan Krah1919b7e2012-03-21 18:25:23 +01004790 @requires_extra_functionality
4791 def test_c_context_templates(self):
4792 self.assertEqual(
4793 C.BasicContext._traps,
4794 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
4795 C.DecUnderflow|C.DecClamped
4796 )
4797 self.assertEqual(
4798 C.DefaultContext._traps,
4799 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
4800 )
Mark Dickinson84230a12010-02-18 14:49:50 +00004801
Stefan Krah1919b7e2012-03-21 18:25:23 +01004802 @requires_extra_functionality
4803 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00004804
Stefan Krah1919b7e2012-03-21 18:25:23 +01004805 # SignalDict coverage
4806 Context = C.Context
4807 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00004808
Stefan Krah1919b7e2012-03-21 18:25:23 +01004809 InvalidOperation = C.InvalidOperation
4810 DivisionByZero = C.DivisionByZero
4811 Overflow = C.Overflow
4812 Subnormal = C.Subnormal
4813 Underflow = C.Underflow
4814 Rounded = C.Rounded
4815 Inexact = C.Inexact
4816 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00004817
Stefan Krah1919b7e2012-03-21 18:25:23 +01004818 DecClamped = C.DecClamped
4819 DecInvalidOperation = C.DecInvalidOperation
4820 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00004821
Stefan Krah1919b7e2012-03-21 18:25:23 +01004822 def assertIsExclusivelySet(signal, signal_dict):
4823 for sig in signal_dict:
4824 if sig == signal:
4825 self.assertTrue(signal_dict[sig])
4826 else:
4827 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00004828
Stefan Krah1919b7e2012-03-21 18:25:23 +01004829 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00004830
Stefan Krah1919b7e2012-03-21 18:25:23 +01004831 # Signal dict methods
4832 self.assertTrue(Overflow in c.traps)
4833 c.clear_traps()
4834 for k in c.traps.keys():
4835 c.traps[k] = True
4836 for v in c.traps.values():
4837 self.assertTrue(v)
4838 c.clear_traps()
4839 for k, v in c.traps.items():
4840 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00004841
Stefan Krah1919b7e2012-03-21 18:25:23 +01004842 self.assertFalse(c.flags.get(Overflow))
4843 self.assertIs(c.flags.get("x"), None)
4844 self.assertEqual(c.flags.get("x", "y"), "y")
4845 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00004846
Stefan Krah1919b7e2012-03-21 18:25:23 +01004847 self.assertEqual(len(c.flags), len(c.traps))
4848 s = sys.getsizeof(c.flags)
4849 s = sys.getsizeof(c.traps)
4850 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00004851
Stefan Krah1919b7e2012-03-21 18:25:23 +01004852 # Set flags/traps.
4853 c.clear_flags()
4854 c._flags = DecClamped
4855 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00004856
Stefan Krah1919b7e2012-03-21 18:25:23 +01004857 c.clear_traps()
4858 c._traps = DecInvalidOperation
4859 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00004860
Stefan Krah1919b7e2012-03-21 18:25:23 +01004861 # Set flags/traps from dictionary.
4862 c.clear_flags()
4863 d = c.flags.copy()
4864 d[DivisionByZero] = True
4865 c.flags = d
4866 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004867
Stefan Krah1919b7e2012-03-21 18:25:23 +01004868 c.clear_traps()
4869 d = c.traps.copy()
4870 d[Underflow] = True
4871 c.traps = d
4872 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004873
Stefan Krah1919b7e2012-03-21 18:25:23 +01004874 # Random constructors
4875 IntSignals = {
4876 Clamped: C.DecClamped,
4877 Rounded: C.DecRounded,
4878 Inexact: C.DecInexact,
4879 Subnormal: C.DecSubnormal,
4880 Underflow: C.DecUnderflow,
4881 Overflow: C.DecOverflow,
4882 DivisionByZero: C.DecDivisionByZero,
4883 InvalidOperation: C.DecIEEEInvalidOperation
4884 }
4885 IntCond = [
4886 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
4887 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
4888 C.DecConversionSyntax,
4889 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01004890
Stefan Krah1919b7e2012-03-21 18:25:23 +01004891 lim = len(OrderedSignals[C])
4892 for r in range(lim):
4893 for t in range(lim):
4894 for round in RoundingModes[C]:
4895 flags = random.sample(OrderedSignals[C], r)
4896 traps = random.sample(OrderedSignals[C], t)
4897 prec = random.randrange(1, 10000)
4898 emin = random.randrange(-10000, 0)
4899 emax = random.randrange(0, 10000)
4900 clamp = random.randrange(0, 2)
4901 caps = random.randrange(0, 2)
4902 cr = random.randrange(0, 2)
4903 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
4904 capitals=caps, clamp=clamp, flags=list(flags),
4905 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00004906
Stefan Krah1919b7e2012-03-21 18:25:23 +01004907 self.assertEqual(c.prec, prec)
4908 self.assertEqual(c.rounding, round)
4909 self.assertEqual(c.Emin, emin)
4910 self.assertEqual(c.Emax, emax)
4911 self.assertEqual(c.capitals, caps)
4912 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00004913
Stefan Krah1919b7e2012-03-21 18:25:23 +01004914 f = 0
4915 for x in flags:
4916 f |= IntSignals[x]
4917 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004918
Stefan Krah1919b7e2012-03-21 18:25:23 +01004919 f = 0
4920 for x in traps:
4921 f |= IntSignals[x]
4922 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004923
Stefan Krah1919b7e2012-03-21 18:25:23 +01004924 for cond in IntCond:
4925 c._flags = cond
4926 self.assertTrue(c._flags&DecIEEEInvalidOperation)
4927 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004928
Stefan Krah1919b7e2012-03-21 18:25:23 +01004929 for cond in IntCond:
4930 c._traps = cond
4931 self.assertTrue(c._traps&DecIEEEInvalidOperation)
4932 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004933
Stefan Krah1919b7e2012-03-21 18:25:23 +01004934 def test_invalid_override(self):
4935 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00004936
Stefan Krah1919b7e2012-03-21 18:25:23 +01004937 try:
4938 from locale import CHAR_MAX
4939 except ImportError:
4940 return
Mark Dickinson84230a12010-02-18 14:49:50 +00004941
Stefan Krah1919b7e2012-03-21 18:25:23 +01004942 def make_grouping(lst):
4943 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00004944
Stefan Krah1919b7e2012-03-21 18:25:23 +01004945 def get_fmt(x, override=None, fmt='n'):
4946 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004947
Stefan Krah1919b7e2012-03-21 18:25:23 +01004948 invalid_grouping = {
4949 'decimal_point' : ',',
4950 'grouping' : make_grouping([255, 255, 0]),
4951 'thousands_sep' : ','
4952 }
4953 invalid_dot = {
4954 'decimal_point' : 'xxxxx',
4955 'grouping' : make_grouping([3, 3, 0]),
4956 'thousands_sep' : ','
4957 }
4958 invalid_sep = {
4959 'decimal_point' : '.',
4960 'grouping' : make_grouping([3, 3, 0]),
4961 'thousands_sep' : 'yyyyy'
4962 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004963
Stefan Krah1919b7e2012-03-21 18:25:23 +01004964 if CHAR_MAX == 127: # negative grouping in override
4965 self.assertRaises(ValueError, get_fmt, 12345,
4966 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004967
Stefan Krah1919b7e2012-03-21 18:25:23 +01004968 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
4969 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004970
Stefan Krah0774e9b2012-04-05 15:21:58 +02004971 def test_exact_conversion(self):
4972 Decimal = C.Decimal
4973 localcontext = C.localcontext
4974 InvalidOperation = C.InvalidOperation
4975
4976 with localcontext() as c:
4977
4978 c.traps[InvalidOperation] = True
4979
4980 # Clamped
4981 x = "0e%d" % sys.maxsize
4982 self.assertRaises(InvalidOperation, Decimal, x)
4983
4984 x = "0e%d" % (-sys.maxsize-1)
4985 self.assertRaises(InvalidOperation, Decimal, x)
4986
4987 # Overflow
4988 x = "1e%d" % sys.maxsize
4989 self.assertRaises(InvalidOperation, Decimal, x)
4990
4991 # Underflow
4992 x = "1e%d" % (-sys.maxsize-1)
4993 self.assertRaises(InvalidOperation, Decimal, x)
4994
Stefan Krahff3eca02012-04-05 15:46:19 +02004995 def test_from_tuple(self):
4996 Decimal = C.Decimal
4997 localcontext = C.localcontext
4998 InvalidOperation = C.InvalidOperation
4999 Overflow = C.Overflow
5000 Underflow = C.Underflow
5001
5002 with localcontext() as c:
5003
5004 c.traps[InvalidOperation] = True
5005 c.traps[Overflow] = True
5006 c.traps[Underflow] = True
5007
5008 # SSIZE_MAX
5009 x = (1, (), sys.maxsize)
5010 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5011 self.assertRaises(InvalidOperation, Decimal, x)
5012
5013 x = (1, (0, 1, 2), sys.maxsize)
5014 self.assertRaises(Overflow, c.create_decimal, x)
5015 self.assertRaises(InvalidOperation, Decimal, x)
5016
5017 # SSIZE_MIN
5018 x = (1, (), -sys.maxsize-1)
5019 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5020 self.assertRaises(InvalidOperation, Decimal, x)
5021
5022 x = (1, (0, 1, 2), -sys.maxsize-1)
5023 self.assertRaises(Underflow, c.create_decimal, x)
5024 self.assertRaises(InvalidOperation, Decimal, x)
5025
5026 # OverflowError
5027 x = (1, (), sys.maxsize+1)
5028 self.assertRaises(OverflowError, c.create_decimal, x)
5029 self.assertRaises(OverflowError, Decimal, x)
5030
5031 x = (1, (), -sys.maxsize-2)
5032 self.assertRaises(OverflowError, c.create_decimal, x)
5033 self.assertRaises(OverflowError, Decimal, x)
5034
5035 # Specials
5036 x = (1, (), "N")
5037 self.assertEqual(str(Decimal(x)), '-sNaN')
5038 x = (1, (0,), "N")
5039 self.assertEqual(str(Decimal(x)), '-sNaN')
5040 x = (1, (0, 1), "N")
5041 self.assertEqual(str(Decimal(x)), '-sNaN1')
5042
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005043
Stefan Krah1919b7e2012-03-21 18:25:23 +01005044all_tests = [
5045 CExplicitConstructionTest, PyExplicitConstructionTest,
5046 CImplicitConstructionTest, PyImplicitConstructionTest,
5047 CFormatTest, PyFormatTest,
5048 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5049 CThreadingTest, PyThreadingTest,
5050 CUsabilityTest, PyUsabilityTest,
5051 CPythonAPItests, PyPythonAPItests,
5052 CContextAPItests, PyContextAPItests,
5053 CContextWithStatement, PyContextWithStatement,
5054 CContextFlags, PyContextFlags,
5055 CSpecialContexts, PySpecialContexts,
5056 CContextInputValidation, PyContextInputValidation,
5057 CContextSubclassing, PyContextSubclassing,
5058 CCoverage, PyCoverage,
5059 CFunctionality, PyFunctionality,
5060 CWhitebox, PyWhitebox,
5061 CIBMTestCases, PyIBMTestCases,
5062]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005063
Stefan Krah1919b7e2012-03-21 18:25:23 +01005064# Delete C tests if _decimal.so is not present.
5065if not C:
5066 all_tests = all_tests[1::2]
5067else:
5068 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005069
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005070
5071def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005072 """ Execute the tests.
5073
Raymond Hettingered20ad82004-09-04 20:09:13 +00005074 Runs all arithmetic tests if arith is True or if the "decimal" resource
5075 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005076 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005077
Stefan Krah1919b7e2012-03-21 18:25:23 +01005078 init(C)
5079 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005080 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00005081 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005082 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005083
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005084 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005085 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005086 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005087 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005088
5089 # Dynamically build custom test definition for each file in the test
5090 # directory and add the definitions to the DecimalTest class. This
5091 # procedure insures that new files do not get skipped.
5092 for filename in os.listdir(directory):
5093 if '.decTest' not in filename or filename.startswith("."):
5094 continue
5095 head, tail = filename.split('.')
5096 if todo_tests is not None and head not in todo_tests:
5097 continue
5098 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005099 setattr(CIBMTestCases, 'test_' + head, tester)
5100 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005101 del filename, head, tail, tester
5102
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005103
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005104 try:
5105 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005106 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005107 from doctest import IGNORE_EXCEPTION_DETAIL
5108 savedecimal = sys.modules['decimal']
5109 if C:
5110 sys.modules['decimal'] = C
5111 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5112 sys.modules['decimal'] = P
5113 run_doctest(P, verbose)
5114 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005115 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005116 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5117 P.setcontext(ORIGINAL_CONTEXT[P])
5118 if not C:
5119 warnings.warn('C tests skipped: no module named _decimal.',
5120 UserWarning)
5121 if not orig_sys_decimal is sys.modules['decimal']:
5122 raise TestFailed("Internal error: unbalanced number of changes to "
5123 "sys.modules['decimal'].")
5124
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005125
5126if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005127 import optparse
5128 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5129 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5130 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5131 (opt, args) = p.parse_args()
5132
5133 if opt.skip:
5134 test_main(arith=False, verbose=True)
5135 elif args:
5136 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005137 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005138 test_main(arith=True, verbose=True)