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