blob: 5195930834d1f38d1f48d905dce0aa44ee39b1db [file] [log] [blame]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001# Copyright (c) 2004 Python Software Foundation.
2# All rights reserved.
3
4# Written by Eric Price <eprice at tjhsst.edu>
5# and Facundo Batista <facundo at taniquetil.com.ar>
6# and Raymond Hettinger <python at rcn.com>
7# and Aahz (aahz at pobox.com)
8# and Tim Peters
9
10"""
11These are the test cases for the Decimal module.
12
13There are two groups of tests, Arithmetic and Behaviour. The former test
14the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
15test the pythonic behaviour according to PEP 327.
16
17Cowlishaw's tests can be downloaded from:
18
Stefan Krah1919b7e2012-03-21 18:25:23 +010019 http://speleotrove.com/decimal/dectest.zip
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000020
21This test module can be called from command line with one parameter (Arithmetic
22or Behaviour) to test each part, or without parameter to test both parts. If
23you're working through IDLE, you can import this test module and call test_main()
24with the corresponding argument.
25"""
26
Christian Heimes400adb02008-02-01 08:12:03 +000027import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000028import os, sys
Mark Dickinsonac256ab2010-04-03 11:08:14 +000029import operator
Mark Dickinsonb1d8e322010-05-22 18:35:36 +000030import warnings
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000031import pickle, copy
Christian Heimes400adb02008-02-01 08:12:03 +000032import unittest
Raymond Hettinger82417ca2009-02-03 03:54:28 +000033import numbers
Stefan Krah1919b7e2012-03-21 18:25:23 +010034import locale
Eric Smith3ab08ca2010-12-04 15:17:38 +000035from test.support import (run_unittest, run_doctest, is_resource_enabled,
36 requires_IEEE_754)
Stefan Krah6fb204a2012-09-28 16:18:54 +020037from test.support import (check_warnings, import_fresh_module, TestFailed,
Stefan Krah6e467042012-11-10 23:09:04 +010038 run_with_locale, cpython_only)
Raymond Hettinger0aeac102004-07-05 22:53:03 +000039import random
Stefan Krah1919b7e2012-03-21 18:25:23 +010040import time
41import warnings
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000042try:
43 import threading
44except ImportError:
45 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000046
Raymond Hettingerfed52962004-07-14 15:41:57 +000047
Stefan Krah1919b7e2012-03-21 18:25:23 +010048C = import_fresh_module('decimal', fresh=['_decimal'])
49P = import_fresh_module('decimal', blocked=['_decimal'])
50orig_sys_decimal = sys.modules['decimal']
51
52# fractions module must import the correct decimal module.
53cfractions = import_fresh_module('fractions', fresh=['fractions'])
54sys.modules['decimal'] = P
55pfractions = import_fresh_module('fractions', fresh=['fractions'])
56sys.modules['decimal'] = C
57fractions = {C:cfractions, P:pfractions}
58sys.modules['decimal'] = orig_sys_decimal
59
60
61# Useful Test Constant
62Signals = {
63 C: tuple(C.getcontext().flags.keys()) if C else None,
64 P: tuple(P.getcontext().flags.keys())
65}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000066# Signals ordered with respect to precedence: when an operation
67# produces multiple signals, signals occurring later in the list
68# should be handled before those occurring earlier in the list.
Stefan Krah1919b7e2012-03-21 18:25:23 +010069OrderedSignals = {
70 C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow,
71 C.Overflow, C.DivisionByZero, C.InvalidOperation,
72 C.FloatOperation] if C else None,
73 P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow,
74 P.Overflow, P.DivisionByZero, P.InvalidOperation,
75 P.FloatOperation]
76}
77def assert_signals(cls, context, attr, expected):
78 d = getattr(context, attr)
79 cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
80
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
Stefan Krah6e467042012-11-10 23:09:04 +0100577 @cpython_only
578 def test_from_legacy_strings(self):
579 import _testcapi
580 Decimal = self.decimal.Decimal
581 context = self.decimal.Context()
582
583 s = _testcapi.unicode_legacy_string('9.999999')
584 self.assertEqual(str(Decimal(s)), '9.999999')
585 self.assertEqual(str(context.create_decimal(s)), '9.999999')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000586
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000587 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100588 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000589
590 #zero
591 d = Decimal( (0, (0,), 0) )
592 self.assertEqual(str(d), '0')
593
594 #int
595 d = Decimal( (1, (4, 5), 0) )
596 self.assertEqual(str(d), '-45')
597
598 #float
599 d = Decimal( (0, (4, 5, 3, 4), -2) )
600 self.assertEqual(str(d), '45.34')
601
602 #weird
603 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
604 self.assertEqual(str(d), '-4.34913534E-17')
605
Stefan Krah1919b7e2012-03-21 18:25:23 +0100606 #inf
607 d = Decimal( (0, (), "F") )
608 self.assertEqual(str(d), 'Infinity')
609
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000610 #wrong number of items
611 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
612
613 #bad sign
614 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000615 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
616 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000617
618 #bad exp
619 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000620 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
621 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000622
623 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100624 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000625 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
626 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000627 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000628 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000629
Stefan Krah1919b7e2012-03-21 18:25:23 +0100630 def test_explicit_from_list(self):
631 Decimal = self.decimal.Decimal
632
633 d = Decimal([0, [0], 0])
634 self.assertEqual(str(d), '0')
635
636 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
637 self.assertEqual(str(d), '-4.34913534E-17')
638
639 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
640 self.assertEqual(str(d), '-4.34913534E-17')
641
642 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
643 self.assertEqual(str(d), '-4.34913534E-17')
644
Antoine Pitrou503ab332010-03-30 18:56:19 +0000645 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100646 Decimal = self.decimal.Decimal
647
Antoine Pitrou503ab332010-03-30 18:56:19 +0000648 self.assertIs(bool(Decimal(0)), False)
649 self.assertIs(bool(Decimal(1)), True)
650 self.assertEqual(Decimal(False), Decimal(0))
651 self.assertEqual(Decimal(True), Decimal(1))
652
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000653 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100654 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000655
656 #positive
657 d = Decimal(45)
658 e = Decimal(d)
659 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000660
661 #very large positive
662 d = Decimal(500000123)
663 e = Decimal(d)
664 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000665
666 #negative
667 d = Decimal(-45)
668 e = Decimal(d)
669 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000670
671 #zero
672 d = Decimal(0)
673 e = Decimal(d)
674 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000675
Raymond Hettinger96798592010-04-02 16:58:27 +0000676 @requires_IEEE_754
677 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100678
679 Decimal = self.decimal.Decimal
680
Raymond Hettinger96798592010-04-02 16:58:27 +0000681 r = Decimal(0.1)
682 self.assertEqual(type(r), Decimal)
683 self.assertEqual(str(r),
684 '0.1000000000000000055511151231257827021181583404541015625')
685 self.assertTrue(Decimal(float('nan')).is_qnan())
686 self.assertTrue(Decimal(float('inf')).is_infinite())
687 self.assertTrue(Decimal(float('-inf')).is_infinite())
688 self.assertEqual(str(Decimal(float('nan'))),
689 str(Decimal('NaN')))
690 self.assertEqual(str(Decimal(float('inf'))),
691 str(Decimal('Infinity')))
692 self.assertEqual(str(Decimal(float('-inf'))),
693 str(Decimal('-Infinity')))
694 self.assertEqual(str(Decimal(float('-0.0'))),
695 str(Decimal('-0')))
696 for i in range(200):
697 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
698 self.assertEqual(x, float(Decimal(x))) # roundtrip
699
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000700 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100701 Decimal = self.decimal.Decimal
702 InvalidOperation = self.decimal.InvalidOperation
703 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000704
Stefan Krah1919b7e2012-03-21 18:25:23 +0100705 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000706 nc.prec = 3
707
708 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000709 d = Decimal()
710 self.assertEqual(str(d), '0')
711 d = nc.create_decimal()
712 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000713
714 # from None
715 self.assertRaises(TypeError, nc.create_decimal, None)
716
717 # from int
718 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000719 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000720 self.assertEqual(nc.create_decimal(45678),
721 nc.create_decimal('457E+2'))
722
723 # from string
724 d = Decimal('456789')
725 self.assertEqual(str(d), '456789')
726 d = nc.create_decimal('456789')
727 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000728 # leading and trailing whitespace should result in a NaN;
729 # spaces are already checked in Cowlishaw's test-suite, so
730 # here we just check that a trailing newline results in a NaN
731 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000732
733 # from tuples
734 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
735 self.assertEqual(str(d), '-4.34913534E-17')
736 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
737 self.assertEqual(str(d), '-4.35E-17')
738
739 # from Decimal
740 prevdec = Decimal(500000123)
741 d = Decimal(prevdec)
742 self.assertEqual(str(d), '500000123')
743 d = nc.create_decimal(prevdec)
744 self.assertEqual(str(d), '5.00E+8')
745
Stefan Krah1919b7e2012-03-21 18:25:23 +0100746 # more integers
747 nc.prec = 28
748 nc.traps[InvalidOperation] = True
749
750 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
751 2**31-1, 2**31, 2**63-1, 2**63]:
752 d = nc.create_decimal(v)
753 self.assertTrue(isinstance(d, Decimal))
754 self.assertEqual(int(d), v)
755
756 nc.prec = 3
757 nc.traps[Rounded] = True
758 self.assertRaises(Rounded, nc.create_decimal, 1234)
759
760 # from string
761 nc.prec = 28
762 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
763 self.assertEqual(str(nc.create_decimal('45')), '45')
764 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
765 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
766
767 # invalid arguments
768 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
769 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
770 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
771
772 # too many NaN payload digits
773 nc.prec = 3
774 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
775 self.assertRaises(InvalidOperation, nc.create_decimal,
776 Decimal('NaN12345'))
777
778 nc.traps[InvalidOperation] = False
779 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
780 self.assertTrue(nc.flags[InvalidOperation])
781
782 nc.flags[InvalidOperation] = False
783 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
784 self.assertTrue(nc.flags[InvalidOperation])
785
786 def test_explicit_context_create_from_float(self):
787
788 Decimal = self.decimal.Decimal
789
790 nc = self.decimal.Context()
791 r = nc.create_decimal(0.1)
792 self.assertEqual(type(r), Decimal)
793 self.assertEqual(str(r), '0.1000000000000000055511151231')
794 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
795 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
796 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
797 self.assertEqual(str(nc.create_decimal(float('nan'))),
798 str(nc.create_decimal('NaN')))
799 self.assertEqual(str(nc.create_decimal(float('inf'))),
800 str(nc.create_decimal('Infinity')))
801 self.assertEqual(str(nc.create_decimal(float('-inf'))),
802 str(nc.create_decimal('-Infinity')))
803 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
804 str(nc.create_decimal('-0')))
805 nc.prec = 100
806 for i in range(200):
807 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
808 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
809
Mark Dickinson345adc42009-08-02 10:14:23 +0000810 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100811 Decimal = self.decimal.Decimal
812
Mark Dickinson345adc42009-08-02 10:14:23 +0000813 test_values = {
814 '\uff11': '1',
815 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
816 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
817 }
818 for input, expected in test_values.items():
819 self.assertEqual(str(Decimal(input)), expected)
820
Stefan Krah1919b7e2012-03-21 18:25:23 +0100821class CExplicitConstructionTest(ExplicitConstructionTest):
822 decimal = C
823class PyExplicitConstructionTest(ExplicitConstructionTest):
824 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000825
Stefan Krah1919b7e2012-03-21 18:25:23 +0100826class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000827 '''Unit tests for Implicit Construction cases of Decimal.'''
828
829 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100830 Decimal = self.decimal.Decimal
831 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000832
833 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100834 Decimal = self.decimal.Decimal
835
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000836 #normal
837 self.assertEqual(str(Decimal(5) + 45), '50')
838 #exceeding precision
839 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
840
841 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100842 Decimal = self.decimal.Decimal
843 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000844
845 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100846 Decimal = self.decimal.Decimal
847 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000848
849 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100850 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000851 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
852
Raymond Hettinger267b8682005-03-27 10:47:39 +0000853 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100854 Decimal = self.decimal.Decimal
855
Raymond Hettinger267b8682005-03-27 10:47:39 +0000856 # Allow other classes to be trained to interact with Decimals
857 class E:
858 def __divmod__(self, other):
859 return 'divmod ' + str(other)
860 def __rdivmod__(self, other):
861 return str(other) + ' rdivmod'
862 def __lt__(self, other):
863 return 'lt ' + str(other)
864 def __gt__(self, other):
865 return 'gt ' + str(other)
866 def __le__(self, other):
867 return 'le ' + str(other)
868 def __ge__(self, other):
869 return 'ge ' + str(other)
870 def __eq__(self, other):
871 return 'eq ' + str(other)
872 def __ne__(self, other):
873 return 'ne ' + str(other)
874
875 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
876 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
877 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
878 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
879 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
880 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
881 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
882 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
883
884 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000885 oplist = [
886 ('+', '__add__', '__radd__'),
887 ('-', '__sub__', '__rsub__'),
888 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000889 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000890 ('%', '__mod__', '__rmod__'),
891 ('//', '__floordiv__', '__rfloordiv__'),
892 ('**', '__pow__', '__rpow__')
893 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000894
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000895 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000896 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
897 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
898 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
899 'str' + lop + '10')
900 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
901 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000902
Stefan Krah1919b7e2012-03-21 18:25:23 +0100903class CImplicitConstructionTest(ImplicitConstructionTest):
904 decimal = C
905class PyImplicitConstructionTest(ImplicitConstructionTest):
906 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000907
Stefan Krah1919b7e2012-03-21 18:25:23 +0100908class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000909 '''Unit tests for the format function.'''
910 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100911 Decimal = self.decimal.Decimal
912
Christian Heimesf16baeb2008-02-29 14:57:44 +0000913 # triples giving a format, a Decimal, and the expected result
914 test_values = [
915 ('e', '0E-15', '0e-15'),
916 ('e', '2.3E-15', '2.3e-15'),
917 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
918 ('e', '2.30000E-15', '2.30000e-15'),
919 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
920 ('e', '1.5', '1.5e+0'),
921 ('e', '0.15', '1.5e-1'),
922 ('e', '0.015', '1.5e-2'),
923 ('e', '0.0000000000015', '1.5e-12'),
924 ('e', '15.0', '1.50e+1'),
925 ('e', '-15', '-1.5e+1'),
926 ('e', '0', '0e+0'),
927 ('e', '0E1', '0e+1'),
928 ('e', '0.0', '0e-1'),
929 ('e', '0.00', '0e-2'),
930 ('.6e', '0E-15', '0.000000e-9'),
931 ('.6e', '0', '0.000000e+6'),
932 ('.6e', '9.999999', '9.999999e+0'),
933 ('.6e', '9.9999999', '1.000000e+1'),
934 ('.6e', '-1.23e5', '-1.230000e+5'),
935 ('.6e', '1.23456789e-3', '1.234568e-3'),
936 ('f', '0', '0'),
937 ('f', '0.0', '0.0'),
938 ('f', '0E-2', '0.00'),
939 ('f', '0.00E-8', '0.0000000000'),
940 ('f', '0E1', '0'), # loses exponent information
941 ('f', '3.2E1', '32'),
942 ('f', '3.2E2', '320'),
943 ('f', '3.20E2', '320'),
944 ('f', '3.200E2', '320.0'),
945 ('f', '3.2E-6', '0.0000032'),
946 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
947 ('.6f', '0E1', '0.000000'),
948 ('.6f', '0', '0.000000'),
949 ('.0f', '0', '0'), # no decimal point
950 ('.0f', '0e-2', '0'),
951 ('.0f', '3.14159265', '3'),
952 ('.1f', '3.14159265', '3.1'),
953 ('.4f', '3.14159265', '3.1416'),
954 ('.6f', '3.14159265', '3.141593'),
955 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
956 ('.8f', '3.14159265', '3.14159265'),
957 ('.9f', '3.14159265', '3.141592650'),
958
959 ('g', '0', '0'),
960 ('g', '0.0', '0.0'),
961 ('g', '0E1', '0e+1'),
962 ('G', '0E1', '0E+1'),
963 ('g', '0E-5', '0.00000'),
964 ('g', '0E-6', '0.000000'),
965 ('g', '0E-7', '0e-7'),
966 ('g', '-0E2', '-0e+2'),
967 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100968 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000969 ('.1g', '3.14159265', '3'),
970 ('.2g', '3.14159265', '3.1'),
971 ('.5g', '3.14159265', '3.1416'),
972 ('.7g', '3.14159265', '3.141593'),
973 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
974 ('.9g', '3.14159265', '3.14159265'),
975 ('.10g', '3.14159265', '3.14159265'), # don't pad
976
977 ('%', '0E1', '0%'),
978 ('%', '0E0', '0%'),
979 ('%', '0E-1', '0%'),
980 ('%', '0E-2', '0%'),
981 ('%', '0E-3', '0.0%'),
982 ('%', '0E-4', '0.00%'),
983
984 ('.3%', '0', '0.000%'), # all zeros treated equally
985 ('.3%', '0E10', '0.000%'),
986 ('.3%', '0E-10', '0.000%'),
987 ('.3%', '2.34', '234.000%'),
988 ('.3%', '1.234567', '123.457%'),
989 ('.0%', '1.23', '123%'),
990
991 ('e', 'NaN', 'NaN'),
992 ('f', '-NaN123', '-NaN123'),
993 ('+g', 'NaN456', '+NaN456'),
994 ('.3e', 'Inf', 'Infinity'),
995 ('.16f', '-Inf', '-Infinity'),
996 ('.0g', '-sNaN', '-sNaN'),
997
998 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000999
Mark Dickinson79f52032009-03-17 23:12:51 +00001000 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001001 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001002 ('<6', '123', '123 '),
1003 ('>6', '123', ' 123'),
1004 ('^6', '123', ' 123 '),
1005 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001006 ('#<10', 'NaN', 'NaN#######'),
1007 ('#<10', '-4.3', '-4.3######'),
1008 ('#<+10', '0.0130', '+0.0130###'),
1009 ('#< 10', '0.0130', ' 0.0130###'),
1010 ('@>10', '-Inf', '@-Infinity'),
1011 ('#>5', '-Inf', '-Infinity'),
1012 ('?^5', '123', '?123?'),
1013 ('%^6', '123', '%123%%'),
1014 (' ^6', '-45.6', '-45.6 '),
1015 ('/=10', '-45.6', '-/////45.6'),
1016 ('/=+10', '45.6', '+/////45.6'),
1017 ('/= 10', '45.6', ' /////45.6'),
1018
1019 # thousands separator
1020 (',', '1234567', '1,234,567'),
1021 (',', '123456', '123,456'),
1022 (',', '12345', '12,345'),
1023 (',', '1234', '1,234'),
1024 (',', '123', '123'),
1025 (',', '12', '12'),
1026 (',', '1', '1'),
1027 (',', '0', '0'),
1028 (',', '-1234567', '-1,234,567'),
1029 (',', '-123456', '-123,456'),
1030 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001031 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001032 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1033 ('+08,', '123456', '+123,456'), # but not if there's a sign
1034 (' 08,', '123456', ' 123,456'),
1035 ('08,', '-123456', '-123,456'),
1036 ('+09,', '123456', '+0,123,456'),
1037 # ... with fractional part...
1038 ('07,', '1234.56', '1,234.56'),
1039 ('08,', '1234.56', '1,234.56'),
1040 ('09,', '1234.56', '01,234.56'),
1041 ('010,', '1234.56', '001,234.56'),
1042 ('011,', '1234.56', '0,001,234.56'),
1043 ('012,', '1234.56', '0,001,234.56'),
1044 ('08,.1f', '1234.5', '01,234.5'),
1045 # no thousands separators in fraction part
1046 (',', '1.23456789', '1.23456789'),
1047 (',%', '123.456789', '12,345.6789%'),
1048 (',e', '123456', '1.23456e+5'),
1049 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001050
1051 # issue 6850
1052 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001053 ]
1054 for fmt, d, result in test_values:
1055 self.assertEqual(format(Decimal(d), fmt), result)
1056
Stefan Krah1919b7e2012-03-21 18:25:23 +01001057 # bytes format argument
1058 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1059
Mark Dickinson79f52032009-03-17 23:12:51 +00001060 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001061 Decimal = self.decimal.Decimal
1062
Mark Dickinson79f52032009-03-17 23:12:51 +00001063 try:
1064 from locale import CHAR_MAX
1065 except ImportError:
1066 return
1067
Stefan Krah1919b7e2012-03-21 18:25:23 +01001068 def make_grouping(lst):
1069 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1070
1071 def get_fmt(x, override=None, fmt='n'):
1072 if self.decimal == C:
1073 return Decimal(x).__format__(fmt, override)
1074 else:
1075 return Decimal(x).__format__(fmt, _localeconv=override)
1076
Mark Dickinson79f52032009-03-17 23:12:51 +00001077 # Set up some localeconv-like dictionaries
1078 en_US = {
1079 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001080 'grouping' : make_grouping([3, 3, 0]),
1081 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001082 }
1083
1084 fr_FR = {
1085 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001086 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001087 'thousands_sep' : ''
1088 }
1089
1090 ru_RU = {
1091 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001092 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001093 'thousands_sep' : ' '
1094 }
1095
1096 crazy = {
1097 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001098 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001099 'thousands_sep' : '-'
1100 }
1101
Stefan Krah1919b7e2012-03-21 18:25:23 +01001102 dotsep_wide = {
1103 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1104 'grouping': make_grouping([3, 3, 0]),
1105 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1106 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001107
1108 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1109 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1110 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1111 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1112
1113 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1114 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1115 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1116 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1117
1118 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1119 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1120 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1121 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1122
Mark Dickinson7303b592009-03-18 08:25:36 +00001123 # zero padding
1124 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1125 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1126 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1127 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1128
1129 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1130 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1131 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1132 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1133 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1134 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1135
1136 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1137 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1138 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1139 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1140 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1141 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1142 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1143 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1144
Stefan Krah1919b7e2012-03-21 18:25:23 +01001145 # wide char separator and decimal point
1146 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1147 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001148
Stefan Krah6fb204a2012-09-28 16:18:54 +02001149 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001150 def test_wide_char_separator_decimal_point(self):
1151 # locale with wide char separator and decimal point
Stefan Krah8a491a82012-09-28 17:17:11 +02001152 import locale
Stefan Krah1919b7e2012-03-21 18:25:23 +01001153 Decimal = self.decimal.Decimal
1154
Stefan Krah8a491a82012-09-28 17:17:11 +02001155 decimal_point = locale.localeconv()['decimal_point']
1156 thousands_sep = locale.localeconv()['thousands_sep']
1157 if decimal_point != '\u066b' or thousands_sep != '\u066c':
1158 return
1159
Stefan Krah1919b7e2012-03-21 18:25:23 +01001160 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1161 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001162
1163class CFormatTest(FormatTest):
1164 decimal = C
1165class PyFormatTest(FormatTest):
1166 decimal = P
1167
1168class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001169 '''Unit tests for all arithmetic operators, binary and unary.'''
1170
1171 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001172 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001173
1174 d1 = Decimal('-11.1')
1175 d2 = Decimal('22.2')
1176
1177 #two Decimals
1178 self.assertEqual(d1+d2, Decimal('11.1'))
1179 self.assertEqual(d2+d1, Decimal('11.1'))
1180
1181 #with other type, left
1182 c = d1 + 5
1183 self.assertEqual(c, Decimal('-6.1'))
1184 self.assertEqual(type(c), type(d1))
1185
1186 #with other type, right
1187 c = 5 + d1
1188 self.assertEqual(c, Decimal('-6.1'))
1189 self.assertEqual(type(c), type(d1))
1190
1191 #inline with decimal
1192 d1 += d2
1193 self.assertEqual(d1, Decimal('11.1'))
1194
1195 #inline with other type
1196 d1 += 5
1197 self.assertEqual(d1, Decimal('16.1'))
1198
1199 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001200 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001201
1202 d1 = Decimal('-11.1')
1203 d2 = Decimal('22.2')
1204
1205 #two Decimals
1206 self.assertEqual(d1-d2, Decimal('-33.3'))
1207 self.assertEqual(d2-d1, Decimal('33.3'))
1208
1209 #with other type, left
1210 c = d1 - 5
1211 self.assertEqual(c, Decimal('-16.1'))
1212 self.assertEqual(type(c), type(d1))
1213
1214 #with other type, right
1215 c = 5 - d1
1216 self.assertEqual(c, Decimal('16.1'))
1217 self.assertEqual(type(c), type(d1))
1218
1219 #inline with decimal
1220 d1 -= d2
1221 self.assertEqual(d1, Decimal('-33.3'))
1222
1223 #inline with other type
1224 d1 -= 5
1225 self.assertEqual(d1, Decimal('-38.3'))
1226
1227 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001228 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001229
1230 d1 = Decimal('-5')
1231 d2 = Decimal('3')
1232
1233 #two Decimals
1234 self.assertEqual(d1*d2, Decimal('-15'))
1235 self.assertEqual(d2*d1, Decimal('-15'))
1236
1237 #with other type, left
1238 c = d1 * 5
1239 self.assertEqual(c, Decimal('-25'))
1240 self.assertEqual(type(c), type(d1))
1241
1242 #with other type, right
1243 c = 5 * d1
1244 self.assertEqual(c, Decimal('-25'))
1245 self.assertEqual(type(c), type(d1))
1246
1247 #inline with decimal
1248 d1 *= d2
1249 self.assertEqual(d1, Decimal('-15'))
1250
1251 #inline with other type
1252 d1 *= 5
1253 self.assertEqual(d1, Decimal('-75'))
1254
1255 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001256 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001257
1258 d1 = Decimal('-5')
1259 d2 = Decimal('2')
1260
1261 #two Decimals
1262 self.assertEqual(d1/d2, Decimal('-2.5'))
1263 self.assertEqual(d2/d1, Decimal('-0.4'))
1264
1265 #with other type, left
1266 c = d1 / 4
1267 self.assertEqual(c, Decimal('-1.25'))
1268 self.assertEqual(type(c), type(d1))
1269
1270 #with other type, right
1271 c = 4 / d1
1272 self.assertEqual(c, Decimal('-0.8'))
1273 self.assertEqual(type(c), type(d1))
1274
1275 #inline with decimal
1276 d1 /= d2
1277 self.assertEqual(d1, Decimal('-2.5'))
1278
1279 #inline with other type
1280 d1 /= 4
1281 self.assertEqual(d1, Decimal('-0.625'))
1282
1283 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001284 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001285
1286 d1 = Decimal('5')
1287 d2 = Decimal('2')
1288
1289 #two Decimals
1290 self.assertEqual(d1//d2, Decimal('2'))
1291 self.assertEqual(d2//d1, Decimal('0'))
1292
1293 #with other type, left
1294 c = d1 // 4
1295 self.assertEqual(c, Decimal('1'))
1296 self.assertEqual(type(c), type(d1))
1297
1298 #with other type, right
1299 c = 7 // d1
1300 self.assertEqual(c, Decimal('1'))
1301 self.assertEqual(type(c), type(d1))
1302
1303 #inline with decimal
1304 d1 //= d2
1305 self.assertEqual(d1, Decimal('2'))
1306
1307 #inline with other type
1308 d1 //= 2
1309 self.assertEqual(d1, Decimal('1'))
1310
1311 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001312 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001313
1314 d1 = Decimal('5')
1315 d2 = Decimal('2')
1316
1317 #two Decimals
1318 self.assertEqual(d1**d2, Decimal('25'))
1319 self.assertEqual(d2**d1, Decimal('32'))
1320
1321 #with other type, left
1322 c = d1 ** 4
1323 self.assertEqual(c, Decimal('625'))
1324 self.assertEqual(type(c), type(d1))
1325
1326 #with other type, right
1327 c = 7 ** d1
1328 self.assertEqual(c, Decimal('16807'))
1329 self.assertEqual(type(c), type(d1))
1330
1331 #inline with decimal
1332 d1 **= d2
1333 self.assertEqual(d1, Decimal('25'))
1334
1335 #inline with other type
1336 d1 **= 4
1337 self.assertEqual(d1, Decimal('390625'))
1338
1339 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001340 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001341
1342 d1 = Decimal('5')
1343 d2 = Decimal('2')
1344
1345 #two Decimals
1346 self.assertEqual(d1%d2, Decimal('1'))
1347 self.assertEqual(d2%d1, Decimal('2'))
1348
1349 #with other type, left
1350 c = d1 % 4
1351 self.assertEqual(c, Decimal('1'))
1352 self.assertEqual(type(c), type(d1))
1353
1354 #with other type, right
1355 c = 7 % d1
1356 self.assertEqual(c, Decimal('2'))
1357 self.assertEqual(type(c), type(d1))
1358
1359 #inline with decimal
1360 d1 %= d2
1361 self.assertEqual(d1, Decimal('1'))
1362
1363 #inline with other type
1364 d1 %= 4
1365 self.assertEqual(d1, Decimal('1'))
1366
1367 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001368 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001369
1370 d1 = Decimal('5')
1371 d2 = Decimal('2')
1372
1373 #two Decimals
1374 (p, q) = divmod(d1, d2)
1375 self.assertEqual(p, Decimal('2'))
1376 self.assertEqual(q, Decimal('1'))
1377 self.assertEqual(type(p), type(d1))
1378 self.assertEqual(type(q), type(d1))
1379
1380 #with other type, left
1381 (p, q) = divmod(d1, 4)
1382 self.assertEqual(p, Decimal('1'))
1383 self.assertEqual(q, Decimal('1'))
1384 self.assertEqual(type(p), type(d1))
1385 self.assertEqual(type(q), type(d1))
1386
1387 #with other type, right
1388 (p, q) = divmod(7, d1)
1389 self.assertEqual(p, Decimal('1'))
1390 self.assertEqual(q, Decimal('2'))
1391 self.assertEqual(type(p), type(d1))
1392 self.assertEqual(type(q), type(d1))
1393
1394 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001395 Decimal = self.decimal.Decimal
1396
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001397 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1398 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1399 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1400
Christian Heimes77c02eb2008-02-09 02:18:51 +00001401 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001402 # comparisons involving signaling nans signal InvalidOperation
1403
1404 # order comparisons (<, <=, >, >=) involving only quiet nans
1405 # also signal InvalidOperation
1406
1407 # equality comparisons (==, !=) involving only quiet nans
1408 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001409 Decimal = self.decimal.Decimal
1410 InvalidOperation = self.decimal.InvalidOperation
1411 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001412
Christian Heimes77c02eb2008-02-09 02:18:51 +00001413 n = Decimal('NaN')
1414 s = Decimal('sNaN')
1415 i = Decimal('Inf')
1416 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001417
1418 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1419 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1420 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1421 equality_ops = operator.eq, operator.ne
1422
1423 # results when InvalidOperation is not trapped
1424 for x, y in qnan_pairs + snan_pairs:
1425 for op in order_ops + equality_ops:
1426 got = op(x, y)
1427 expected = True if op is operator.ne else False
1428 self.assertIs(expected, got,
1429 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1430 "got {4!r}".format(
1431 expected, op.__name__, x, y, got))
1432
1433 # repeat the above, but this time trap the InvalidOperation
1434 with localcontext() as ctx:
1435 ctx.traps[InvalidOperation] = 1
1436
1437 for x, y in qnan_pairs:
1438 for op in equality_ops:
1439 got = op(x, y)
1440 expected = True if op is operator.ne else False
1441 self.assertIs(expected, got,
1442 "expected {0!r} for "
1443 "operator.{1}({2!r}, {3!r}); "
1444 "got {4!r}".format(
1445 expected, op.__name__, x, y, got))
1446
1447 for x, y in snan_pairs:
1448 for op in equality_ops:
1449 self.assertRaises(InvalidOperation, operator.eq, x, y)
1450 self.assertRaises(InvalidOperation, operator.ne, x, y)
1451
1452 for x, y in qnan_pairs + snan_pairs:
1453 for op in order_ops:
1454 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001455
Mark Dickinson84230a12010-02-18 14:49:50 +00001456 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001457 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001458
Stefan Krah1919b7e2012-03-21 18:25:23 +01001459 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001460 self.assertEqual(Decimal(1).copy_sign(-2), d)
1461 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1462
Stefan Krah1919b7e2012-03-21 18:25:23 +01001463class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1464 decimal = C
1465class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1466 decimal = P
1467
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001468# The following are two functions used to test threading in the next class
1469
1470def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001471 Decimal = cls.decimal.Decimal
1472 InvalidOperation = cls.decimal.InvalidOperation
1473 DivisionByZero = cls.decimal.DivisionByZero
1474 Overflow = cls.decimal.Overflow
1475 Underflow = cls.decimal.Underflow
1476 Inexact = cls.decimal.Inexact
1477 getcontext = cls.decimal.getcontext
1478 localcontext = cls.decimal.localcontext
1479
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001480 d1 = Decimal(1)
1481 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001482 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001483
Stefan Krah1919b7e2012-03-21 18:25:23 +01001484 cls.finish1.set()
1485 cls.synchro.wait()
1486
1487 test2 = d1/d3
1488 with localcontext() as c2:
1489 cls.assertTrue(c2.flags[Inexact])
1490 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1491 cls.assertTrue(c2.flags[DivisionByZero])
1492 with localcontext() as c3:
1493 cls.assertTrue(c3.flags[Inexact])
1494 cls.assertTrue(c3.flags[DivisionByZero])
1495 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1496 cls.assertTrue(c3.flags[InvalidOperation])
1497 del c3
1498 cls.assertFalse(c2.flags[InvalidOperation])
1499 del c2
1500
1501 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1502 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1503
1504 c1 = getcontext()
1505 cls.assertTrue(c1.flags[Inexact])
1506 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1507 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001508 return
1509
1510def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001511 Decimal = cls.decimal.Decimal
1512 InvalidOperation = cls.decimal.InvalidOperation
1513 DivisionByZero = cls.decimal.DivisionByZero
1514 Overflow = cls.decimal.Overflow
1515 Underflow = cls.decimal.Underflow
1516 Inexact = cls.decimal.Inexact
1517 getcontext = cls.decimal.getcontext
1518 localcontext = cls.decimal.localcontext
1519
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001520 d1 = Decimal(1)
1521 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001522 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001523
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001524 thiscontext = getcontext()
1525 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001526 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001527
1528 with localcontext() as c2:
1529 cls.assertTrue(c2.flags[Inexact])
1530 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1531 cls.assertTrue(c2.flags[Overflow])
1532 with localcontext(thiscontext) as c3:
1533 cls.assertTrue(c3.flags[Inexact])
1534 cls.assertFalse(c3.flags[Overflow])
1535 c3.traps[Underflow] = True
1536 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1537 cls.assertTrue(c3.flags[Underflow])
1538 del c3
1539 cls.assertFalse(c2.flags[Underflow])
1540 cls.assertFalse(c2.traps[Underflow])
1541 del c2
1542
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001543 cls.synchro.set()
1544 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001545
Stefan Krah1919b7e2012-03-21 18:25:23 +01001546 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001547 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001548
1549 cls.assertFalse(thiscontext.traps[Underflow])
1550 cls.assertTrue(thiscontext.flags[Inexact])
1551 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1552 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001553 return
1554
Stefan Krah1919b7e2012-03-21 18:25:23 +01001555class ThreadingTest(unittest.TestCase):
1556 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001557
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001558 # Take care executing this test from IDLE, there's an issue in threading
1559 # that hangs IDLE and I couldn't find it
1560
1561 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001562 DefaultContext = self.decimal.DefaultContext
1563
1564 if self.decimal == C and not self.decimal.HAVE_THREADS:
1565 self.skipTest("compiled without threading")
1566 # Test the "threading isolation" of a Context. Also test changing
1567 # the DefaultContext, which acts as a template for the thread-local
1568 # contexts.
1569 save_prec = DefaultContext.prec
1570 save_emax = DefaultContext.Emax
1571 save_emin = DefaultContext.Emin
1572 DefaultContext.prec = 24
1573 DefaultContext.Emax = 425000000
1574 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001575
1576 self.synchro = threading.Event()
1577 self.finish1 = threading.Event()
1578 self.finish2 = threading.Event()
1579
1580 th1 = threading.Thread(target=thfunc1, args=(self,))
1581 th2 = threading.Thread(target=thfunc2, args=(self,))
1582
1583 th1.start()
1584 th2.start()
1585
1586 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001587 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001588
1589 for sig in Signals[self.decimal]:
1590 self.assertFalse(DefaultContext.flags[sig])
1591
1592 DefaultContext.prec = save_prec
1593 DefaultContext.Emax = save_emax
1594 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001595 return
1596
Stefan Krah1919b7e2012-03-21 18:25:23 +01001597@unittest.skipUnless(threading, 'threading required')
1598class CThreadingTest(ThreadingTest):
1599 decimal = C
1600@unittest.skipUnless(threading, 'threading required')
1601class PyThreadingTest(ThreadingTest):
1602 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001603
Stefan Krah1919b7e2012-03-21 18:25:23 +01001604class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001605 '''Unit tests for Usability cases of Decimal.'''
1606
1607 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001608
Stefan Krah1919b7e2012-03-21 18:25:23 +01001609 Decimal = self.decimal.Decimal
1610
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001611 da = Decimal('23.42')
1612 db = Decimal('23.42')
1613 dc = Decimal('45')
1614
1615 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001616 self.assertGreater(dc, da)
1617 self.assertGreaterEqual(dc, da)
1618 self.assertLess(da, dc)
1619 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001620 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001621 self.assertNotEqual(da, dc)
1622 self.assertLessEqual(da, db)
1623 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001624
1625 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001626 self.assertGreater(dc, 23)
1627 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001628 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001629
1630 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001631 self.assertNotEqual(da, 'ugly')
1632 self.assertNotEqual(da, 32.7)
1633 self.assertNotEqual(da, object())
1634 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001635
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001636 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001637 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001638 b = a[:]
1639 random.shuffle(a)
1640 a.sort()
1641 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001642
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001643 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001644 Decimal = self.decimal.Decimal
1645
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001646 da = Decimal('0.25')
1647 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001648 self.assertLess(da, 3.0)
1649 self.assertLessEqual(da, 3.0)
1650 self.assertGreater(db, 0.25)
1651 self.assertGreaterEqual(db, 0.25)
1652 self.assertNotEqual(da, 1.5)
1653 self.assertEqual(da, 0.25)
1654 self.assertGreater(3.0, da)
1655 self.assertGreaterEqual(3.0, da)
1656 self.assertLess(0.25, db)
1657 self.assertLessEqual(0.25, db)
1658 self.assertNotEqual(0.25, db)
1659 self.assertEqual(3.0, db)
1660 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001661
Stefan Krah1919b7e2012-03-21 18:25:23 +01001662 def test_decimal_complex_comparison(self):
1663 Decimal = self.decimal.Decimal
1664
1665 da = Decimal('0.25')
1666 db = Decimal('3.0')
1667 self.assertNotEqual(da, (1.5+0j))
1668 self.assertNotEqual((1.5+0j), da)
1669 self.assertEqual(da, (0.25+0j))
1670 self.assertEqual((0.25+0j), da)
1671 self.assertEqual((3.0+0j), db)
1672 self.assertEqual(db, (3.0+0j))
1673
1674 self.assertNotEqual(db, (3.0+1j))
1675 self.assertNotEqual((3.0+1j), db)
1676
1677 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1678 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1679 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1680 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1681
1682 def test_decimal_fraction_comparison(self):
1683 D = self.decimal.Decimal
1684 F = fractions[self.decimal].Fraction
1685 Context = self.decimal.Context
1686 localcontext = self.decimal.localcontext
1687 InvalidOperation = self.decimal.InvalidOperation
1688
1689
1690 emax = C.MAX_EMAX if C else 999999999
1691 emin = C.MIN_EMIN if C else -999999999
1692 etiny = C.MIN_ETINY if C else -1999999997
1693 c = Context(Emax=emax, Emin=emin)
1694
1695 with localcontext(c):
1696 c.prec = emax
1697 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1698 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1699 self.assertLess(F(0,1), D("1e" + str(etiny)))
1700 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1701 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1702 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1703
1704 self.assertEqual(D("0.1"), F(1,10))
1705 self.assertEqual(F(1,10), D("0.1"))
1706
1707 c.prec = 300
1708 self.assertNotEqual(D(1)/3, F(1,3))
1709 self.assertNotEqual(F(1,3), D(1)/3)
1710
1711 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1712 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1713
1714 self.assertGreater(D('inf'), F(99999999999,123))
1715 self.assertGreater(D('inf'), F(-99999999999,123))
1716 self.assertLess(D('-inf'), F(99999999999,123))
1717 self.assertLess(D('-inf'), F(-99999999999,123))
1718
1719 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1720 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1721 self.assertNotEqual(D('nan'), F(-9,123))
1722 self.assertNotEqual(F(-9,123), D('nan'))
1723
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001724 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001725 Decimal = self.decimal.Decimal
1726
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001727 d = Decimal('43.24')
1728 c = copy.copy(d)
1729 self.assertEqual(id(c), id(d))
1730 dc = copy.deepcopy(d)
1731 self.assertEqual(id(dc), id(d))
1732
1733 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001734
1735 Decimal = self.decimal.Decimal
1736 localcontext = self.decimal.localcontext
1737
Stefan Krahdc817b22010-11-17 11:16:34 +00001738 def hashit(d):
1739 a = hash(d)
1740 b = d.__hash__()
1741 self.assertEqual(a, b)
1742 return a
1743
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001744 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001745 hashit(Decimal(23))
1746 hashit(Decimal('Infinity'))
1747 hashit(Decimal('-Infinity'))
1748 hashit(Decimal('nan123'))
1749 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001750
1751 test_values = [Decimal(sign*(2**m + n))
1752 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001753 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001754 for n in range(-10, 10)
1755 for sign in [-1, 1]]
1756 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001757 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001758 Decimal("-0"), # zeros
1759 Decimal("0.00"),
1760 Decimal("-0.000"),
1761 Decimal("0E10"),
1762 Decimal("-0E12"),
1763 Decimal("10.0"), # negative exponent
1764 Decimal("-23.00000"),
1765 Decimal("1230E100"), # positive exponent
1766 Decimal("-4.5678E50"),
1767 # a value for which hash(n) != hash(n % (2**64-1))
1768 # in Python pre-2.6
1769 Decimal(2**64 + 2**32 - 1),
1770 # selection of values which fail with the old (before
1771 # version 2.6) long.__hash__
1772 Decimal("1.634E100"),
1773 Decimal("90.697E100"),
1774 Decimal("188.83E100"),
1775 Decimal("1652.9E100"),
1776 Decimal("56531E100"),
1777 ])
1778
1779 # check that hash(d) == hash(int(d)) for integral values
1780 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001781 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001782
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001783 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001784 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001785 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001786 self.assertTrue(hashit(Decimal('Inf')))
1787 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001788
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001789 # check that the hashes of a Decimal float match when they
1790 # represent exactly the same values
1791 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1792 '34.0', '2.5', '112390.625', '-0.515625']
1793 for s in test_strings:
1794 f = float(s)
1795 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001796 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001797
Stefan Krah1919b7e2012-03-21 18:25:23 +01001798 with localcontext() as c:
1799 # check that the value of the hash doesn't depend on the
1800 # current context (issue #1757)
1801 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001802
Stefan Krah1919b7e2012-03-21 18:25:23 +01001803 c.prec = 6
1804 h1 = hashit(x)
1805 c.prec = 10
1806 h2 = hashit(x)
1807 c.prec = 16
1808 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001809
Stefan Krah1919b7e2012-03-21 18:25:23 +01001810 self.assertEqual(h1, h2)
1811 self.assertEqual(h1, h3)
1812
1813 c.prec = 10000
1814 x = 1100 ** 1248
1815 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001816
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001817 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001818 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001819
1820 d1 = Decimal('15.32')
1821 d2 = Decimal('28.5')
1822 l1 = 15
1823 l2 = 28
1824
1825 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001826 self.assertIs(min(d1,d2), d1)
1827 self.assertIs(min(d2,d1), d1)
1828 self.assertIs(max(d1,d2), d2)
1829 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001830
1831 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001832 self.assertIs(min(d1,l2), d1)
1833 self.assertIs(min(l2,d1), d1)
1834 self.assertIs(max(l1,d2), d2)
1835 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001836
1837 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001838 Decimal = self.decimal.Decimal
1839
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001840 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001841 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001842 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001843 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001844
1845 def test_tostring_methods(self):
1846 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001847 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001848
1849 d = Decimal('15.32')
1850 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001851 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001852
1853 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001854 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001855 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001856
1857 d1 = Decimal('66')
1858 d2 = Decimal('15.32')
1859
1860 #int
1861 self.assertEqual(int(d1), 66)
1862 self.assertEqual(int(d2), 15)
1863
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001864 #float
1865 self.assertEqual(float(d1), 66)
1866 self.assertEqual(float(d2), 15.32)
1867
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001868 #floor
1869 test_pairs = [
1870 ('123.00', 123),
1871 ('3.2', 3),
1872 ('3.54', 3),
1873 ('3.899', 3),
1874 ('-2.3', -3),
1875 ('-11.0', -11),
1876 ('0.0', 0),
1877 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001878 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001879 ]
1880 for d, i in test_pairs:
1881 self.assertEqual(math.floor(Decimal(d)), i)
1882 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1883 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1884 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1885 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1886 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1887
1888 #ceiling
1889 test_pairs = [
1890 ('123.00', 123),
1891 ('3.2', 4),
1892 ('3.54', 4),
1893 ('3.899', 4),
1894 ('-2.3', -2),
1895 ('-11.0', -11),
1896 ('0.0', 0),
1897 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001898 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001899 ]
1900 for d, i in test_pairs:
1901 self.assertEqual(math.ceil(Decimal(d)), i)
1902 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1903 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1904 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1905 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1906 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1907
1908 #round, single argument
1909 test_pairs = [
1910 ('123.00', 123),
1911 ('3.2', 3),
1912 ('3.54', 4),
1913 ('3.899', 4),
1914 ('-2.3', -2),
1915 ('-11.0', -11),
1916 ('0.0', 0),
1917 ('-0E3', 0),
1918 ('-3.5', -4),
1919 ('-2.5', -2),
1920 ('-1.5', -2),
1921 ('-0.5', 0),
1922 ('0.5', 0),
1923 ('1.5', 2),
1924 ('2.5', 2),
1925 ('3.5', 4),
1926 ]
1927 for d, i in test_pairs:
1928 self.assertEqual(round(Decimal(d)), i)
1929 self.assertRaises(ValueError, round, Decimal('-NaN'))
1930 self.assertRaises(ValueError, round, Decimal('sNaN'))
1931 self.assertRaises(ValueError, round, Decimal('NaN123'))
1932 self.assertRaises(OverflowError, round, Decimal('Inf'))
1933 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1934
1935 #round, two arguments; this is essentially equivalent
1936 #to quantize, which is already extensively tested
1937 test_triples = [
1938 ('123.456', -4, '0E+4'),
1939 ('123.456', -3, '0E+3'),
1940 ('123.456', -2, '1E+2'),
1941 ('123.456', -1, '1.2E+2'),
1942 ('123.456', 0, '123'),
1943 ('123.456', 1, '123.5'),
1944 ('123.456', 2, '123.46'),
1945 ('123.456', 3, '123.456'),
1946 ('123.456', 4, '123.4560'),
1947 ('123.455', 2, '123.46'),
1948 ('123.445', 2, '123.44'),
1949 ('Inf', 4, 'NaN'),
1950 ('-Inf', -23, 'NaN'),
1951 ('sNaN314', 3, 'NaN314'),
1952 ]
1953 for d, n, r in test_triples:
1954 self.assertEqual(str(round(Decimal(d), n)), r)
1955
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001956 def test_nan_to_float(self):
1957 # Test conversions of decimal NANs to float.
1958 # See http://bugs.python.org/issue15544
1959 Decimal = self.decimal.Decimal
1960 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1961 f = float(Decimal(s))
1962 self.assertTrue(math.isnan(f))
1963 sign = math.copysign(1.0, f)
1964 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1965
1966 def test_snan_to_float(self):
1967 Decimal = self.decimal.Decimal
1968 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1969 d = Decimal(s)
1970 self.assertRaises(ValueError, float, d)
1971
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001972 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001973 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001974
1975 #with zero
1976 d = Decimal( (0, (0,), 0) )
1977 self.assertEqual(d, eval(repr(d)))
1978
1979 #int
1980 d = Decimal( (1, (4, 5), 0) )
1981 self.assertEqual(d, eval(repr(d)))
1982
1983 #float
1984 d = Decimal( (0, (4, 5, 3, 4), -2) )
1985 self.assertEqual(d, eval(repr(d)))
1986
1987 #weird
1988 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1989 self.assertEqual(d, eval(repr(d)))
1990
1991 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001992 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001993
1994 #with zero
1995 d = Decimal(0)
1996 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1997
1998 #int
1999 d = Decimal(-45)
2000 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2001
2002 #complicated string
2003 d = Decimal("-4.34913534E-17")
2004 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2005
Stefan Krah76e12172012-09-10 19:34:58 +02002006 # The '0' coefficient is implementation specific to decimal.py.
2007 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002008 d = Decimal("Infinity")
2009 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2010
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002011 #leading zeros in coefficient should be stripped
2012 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2013 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2014 d = Decimal( (1, (0, 0, 0), 37) )
2015 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2016 d = Decimal( (1, (), 37) )
2017 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2018
2019 #leading zeros in NaN diagnostic info should be stripped
2020 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2021 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2022 d = Decimal( (1, (0, 0, 0), 'N') )
2023 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2024 d = Decimal( (1, (), 'n') )
2025 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2026
Stefan Krah76e12172012-09-10 19:34:58 +02002027 # For infinities, decimal.py has always silently accepted any
2028 # coefficient tuple.
2029 d = Decimal( (0, (0,), 'F') )
2030 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2031 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2032 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2033 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2034 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002035
Stefan Krah1919b7e2012-03-21 18:25:23 +01002036 def test_subclassing(self):
2037 # Different behaviours when subclassing Decimal
2038 Decimal = self.decimal.Decimal
2039
2040 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002041 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002042
2043 d1 = MyDecimal(1)
2044 d2 = MyDecimal(2)
2045 d = d1 + d2
2046 self.assertIs(type(d), Decimal)
2047
2048 d = d1.max(d2)
2049 self.assertIs(type(d), Decimal)
2050
2051 d = copy.copy(d1)
2052 self.assertIs(type(d), MyDecimal)
2053 self.assertEqual(d, d1)
2054
2055 d = copy.deepcopy(d1)
2056 self.assertIs(type(d), MyDecimal)
2057 self.assertEqual(d, d1)
2058
Stefan Krah0f82b762012-11-08 11:17:29 +01002059 # Decimal(Decimal)
2060 d = Decimal('1.0')
2061 x = Decimal(d)
2062 self.assertIs(type(x), Decimal)
2063 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002064
Stefan Krah0f82b762012-11-08 11:17:29 +01002065 # MyDecimal(Decimal)
2066 m = MyDecimal(d)
2067 self.assertIs(type(m), MyDecimal)
2068 self.assertEqual(m, d)
2069 self.assertIs(m.y, None)
2070
2071 # Decimal(MyDecimal)
2072 x = Decimal(m)
2073 self.assertIs(type(x), Decimal)
2074 self.assertEqual(x, d)
2075
2076 # MyDecimal(MyDecimal)
2077 m.y = 9
2078 x = MyDecimal(m)
2079 self.assertIs(type(x), MyDecimal)
2080 self.assertEqual(x, d)
2081 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002082
Stefan Krah1919b7e2012-03-21 18:25:23 +01002083 def test_implicit_context(self):
2084 Decimal = self.decimal.Decimal
2085 getcontext = self.decimal.getcontext
2086
2087 # Check results when context given implicitly. (Issue 2478)
2088 c = getcontext()
2089 self.assertEqual(str(Decimal(0).sqrt()),
2090 str(c.sqrt(Decimal(0))))
2091
2092 def test_conversions_from_int(self):
2093 # Check that methods taking a second Decimal argument will
2094 # always accept an integer in place of a Decimal.
2095 Decimal = self.decimal.Decimal
2096
2097 self.assertEqual(Decimal(4).compare(3),
2098 Decimal(4).compare(Decimal(3)))
2099 self.assertEqual(Decimal(4).compare_signal(3),
2100 Decimal(4).compare_signal(Decimal(3)))
2101 self.assertEqual(Decimal(4).compare_total(3),
2102 Decimal(4).compare_total(Decimal(3)))
2103 self.assertEqual(Decimal(4).compare_total_mag(3),
2104 Decimal(4).compare_total_mag(Decimal(3)))
2105 self.assertEqual(Decimal(10101).logical_and(1001),
2106 Decimal(10101).logical_and(Decimal(1001)))
2107 self.assertEqual(Decimal(10101).logical_or(1001),
2108 Decimal(10101).logical_or(Decimal(1001)))
2109 self.assertEqual(Decimal(10101).logical_xor(1001),
2110 Decimal(10101).logical_xor(Decimal(1001)))
2111 self.assertEqual(Decimal(567).max(123),
2112 Decimal(567).max(Decimal(123)))
2113 self.assertEqual(Decimal(567).max_mag(123),
2114 Decimal(567).max_mag(Decimal(123)))
2115 self.assertEqual(Decimal(567).min(123),
2116 Decimal(567).min(Decimal(123)))
2117 self.assertEqual(Decimal(567).min_mag(123),
2118 Decimal(567).min_mag(Decimal(123)))
2119 self.assertEqual(Decimal(567).next_toward(123),
2120 Decimal(567).next_toward(Decimal(123)))
2121 self.assertEqual(Decimal(1234).quantize(100),
2122 Decimal(1234).quantize(Decimal(100)))
2123 self.assertEqual(Decimal(768).remainder_near(1234),
2124 Decimal(768).remainder_near(Decimal(1234)))
2125 self.assertEqual(Decimal(123).rotate(1),
2126 Decimal(123).rotate(Decimal(1)))
2127 self.assertEqual(Decimal(1234).same_quantum(1000),
2128 Decimal(1234).same_quantum(Decimal(1000)))
2129 self.assertEqual(Decimal('9.123').scaleb(-100),
2130 Decimal('9.123').scaleb(Decimal(-100)))
2131 self.assertEqual(Decimal(456).shift(-1),
2132 Decimal(456).shift(Decimal(-1)))
2133
2134 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2135 Decimal(-12).fma(Decimal(45), Decimal(67)))
2136 self.assertEqual(Decimal(-12).fma(45, 67),
2137 Decimal(-12).fma(Decimal(45), Decimal(67)))
2138 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2139 Decimal(-12).fma(Decimal(45), Decimal(67)))
2140
2141class CUsabilityTest(UsabilityTest):
2142 decimal = C
2143class PyUsabilityTest(UsabilityTest):
2144 decimal = P
2145
2146class PythonAPItests(unittest.TestCase):
2147
2148 def test_abc(self):
2149 Decimal = self.decimal.Decimal
2150
2151 self.assertTrue(issubclass(Decimal, numbers.Number))
2152 self.assertFalse(issubclass(Decimal, numbers.Real))
2153 self.assertIsInstance(Decimal(0), numbers.Number)
2154 self.assertNotIsInstance(Decimal(0), numbers.Real)
2155
2156 def test_pickle(self):
2157 Decimal = self.decimal.Decimal
2158
2159 savedecimal = sys.modules['decimal']
2160
2161 # Round trip
2162 sys.modules['decimal'] = self.decimal
2163 d = Decimal('-3.141590000')
2164 p = pickle.dumps(d)
2165 e = pickle.loads(p)
2166 self.assertEqual(d, e)
2167
2168 if C:
2169 # Test interchangeability
2170 x = C.Decimal('-3.123e81723')
2171 y = P.Decimal('-3.123e81723')
2172
2173 sys.modules['decimal'] = C
2174 sx = pickle.dumps(x)
2175 sys.modules['decimal'] = P
2176 r = pickle.loads(sx)
2177 self.assertIsInstance(r, P.Decimal)
2178 self.assertEqual(r, y)
2179
2180 sys.modules['decimal'] = P
2181 sy = pickle.dumps(y)
2182 sys.modules['decimal'] = C
2183 r = pickle.loads(sy)
2184 self.assertIsInstance(r, C.Decimal)
2185 self.assertEqual(r, x)
2186
2187 sys.modules['decimal'] = savedecimal
2188
2189 def test_int(self):
2190 Decimal = self.decimal.Decimal
2191 ROUND_DOWN = self.decimal.ROUND_DOWN
2192
2193 for x in range(-250, 250):
2194 s = '%0.2f' % (x / 100.0)
2195 # should work the same as for floats
2196 self.assertEqual(int(Decimal(s)), int(float(s)))
2197 # should work the same as to_integral in the ROUND_DOWN mode
2198 d = Decimal(s)
2199 r = d.to_integral(ROUND_DOWN)
2200 self.assertEqual(Decimal(int(d)), r)
2201
2202 self.assertRaises(ValueError, int, Decimal('-nan'))
2203 self.assertRaises(ValueError, int, Decimal('snan'))
2204 self.assertRaises(OverflowError, int, Decimal('inf'))
2205 self.assertRaises(OverflowError, int, Decimal('-inf'))
2206
2207 def test_trunc(self):
2208 Decimal = self.decimal.Decimal
2209 ROUND_DOWN = self.decimal.ROUND_DOWN
2210
2211 for x in range(-250, 250):
2212 s = '%0.2f' % (x / 100.0)
2213 # should work the same as for floats
2214 self.assertEqual(int(Decimal(s)), int(float(s)))
2215 # should work the same as to_integral in the ROUND_DOWN mode
2216 d = Decimal(s)
2217 r = d.to_integral(ROUND_DOWN)
2218 self.assertEqual(Decimal(math.trunc(d)), r)
2219
2220 def test_from_float(self):
2221
2222 Decimal = self.decimal.Decimal
2223
2224 class MyDecimal(Decimal):
2225 pass
2226
2227 self.assertTrue(issubclass(MyDecimal, Decimal))
2228
2229 r = MyDecimal.from_float(0.1)
2230 self.assertEqual(type(r), MyDecimal)
2231 self.assertEqual(str(r),
2232 '0.1000000000000000055511151231257827021181583404541015625')
2233 bigint = 12345678901234567890123456789
2234 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2235 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2236 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2237 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2238 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2239 str(Decimal('NaN')))
2240 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2241 str(Decimal('Infinity')))
2242 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2243 str(Decimal('-Infinity')))
2244 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2245 for i in range(200):
2246 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2247 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2248
2249 def test_create_decimal_from_float(self):
2250 Decimal = self.decimal.Decimal
2251 Context = self.decimal.Context
2252 ROUND_DOWN = self.decimal.ROUND_DOWN
2253 ROUND_UP = self.decimal.ROUND_UP
2254 Inexact = self.decimal.Inexact
2255
2256 context = Context(prec=5, rounding=ROUND_DOWN)
2257 self.assertEqual(
2258 context.create_decimal_from_float(math.pi),
2259 Decimal('3.1415')
2260 )
2261 context = Context(prec=5, rounding=ROUND_UP)
2262 self.assertEqual(
2263 context.create_decimal_from_float(math.pi),
2264 Decimal('3.1416')
2265 )
2266 context = Context(prec=5, traps=[Inexact])
2267 self.assertRaises(
2268 Inexact,
2269 context.create_decimal_from_float,
2270 math.pi
2271 )
2272 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2273 "Decimal('-0')")
2274 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2275 "Decimal('1')")
2276 self.assertEqual(repr(context.create_decimal_from_float(10)),
2277 "Decimal('10')")
2278
2279 def test_quantize(self):
2280 Decimal = self.decimal.Decimal
2281 Context = self.decimal.Context
2282 InvalidOperation = self.decimal.InvalidOperation
2283 ROUND_DOWN = self.decimal.ROUND_DOWN
2284
2285 c = Context(Emax=99999, Emin=-99999)
2286 self.assertEqual(
2287 Decimal('7.335').quantize(Decimal('.01')),
2288 Decimal('7.34')
2289 )
2290 self.assertEqual(
2291 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2292 Decimal('7.33')
2293 )
2294 self.assertRaises(
2295 InvalidOperation,
2296 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2297 )
2298
2299 c = Context()
2300 d = Decimal("0.871831e800")
2301 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2302 self.assertEqual(x, Decimal('8.71E+799'))
2303
2304 def test_complex(self):
2305 Decimal = self.decimal.Decimal
2306
2307 x = Decimal("9.8182731e181273")
2308 self.assertEqual(x.real, x)
2309 self.assertEqual(x.imag, 0)
2310 self.assertEqual(x.conjugate(), x)
2311
2312 x = Decimal("1")
2313 self.assertEqual(complex(x), complex(float(1)))
2314
2315 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2316 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2317 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2318 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2319
2320 def test_named_parameters(self):
2321 D = self.decimal.Decimal
2322 Context = self.decimal.Context
2323 localcontext = self.decimal.localcontext
2324 InvalidOperation = self.decimal.InvalidOperation
2325 Overflow = self.decimal.Overflow
2326
2327 xc = Context()
2328 xc.prec = 1
2329 xc.Emax = 1
2330 xc.Emin = -1
2331
2332 with localcontext() as c:
2333 c.clear_flags()
2334
2335 self.assertEqual(D(9, xc), 9)
2336 self.assertEqual(D(9, context=xc), 9)
2337 self.assertEqual(D(context=xc, value=9), 9)
2338 self.assertEqual(D(context=xc), 0)
2339 xc.clear_flags()
2340 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2341 self.assertTrue(xc.flags[InvalidOperation])
2342 self.assertFalse(c.flags[InvalidOperation])
2343
2344 xc.clear_flags()
2345 self.assertEqual(D(2).exp(context=xc), 7)
2346 self.assertRaises(Overflow, D(8).exp, context=xc)
2347 self.assertTrue(xc.flags[Overflow])
2348 self.assertFalse(c.flags[Overflow])
2349
2350 xc.clear_flags()
2351 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2352 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2353 self.assertTrue(xc.flags[InvalidOperation])
2354 self.assertFalse(c.flags[InvalidOperation])
2355
2356 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2357 self.assertEqual(D(-1).next_minus(context=xc), -2)
2358 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2359 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2360 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2361 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2362 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2363 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2364
2365 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2366 xc.clear_flags()
2367 self.assertRaises(InvalidOperation,
2368 D("0").compare_signal, D('nan'), context=xc)
2369 self.assertTrue(xc.flags[InvalidOperation])
2370 self.assertFalse(c.flags[InvalidOperation])
2371 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2372 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2373 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2374 D('-0.3'))
2375 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2376 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2377 D('0.0'))
2378 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2379 xc.clear_flags()
2380 self.assertRaises(InvalidOperation,
2381 D("0.2").quantize, D('1e10'), context=xc)
2382 self.assertTrue(xc.flags[InvalidOperation])
2383 self.assertFalse(c.flags[InvalidOperation])
2384 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2385 D('-0.5'))
2386
2387 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2388 D('7E+1'))
2389
2390 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2391 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2392 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2393 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2394 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2395 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2396 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2397 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2398
2399 self.assertFalse(D("0.01").is_normal(context=xc))
2400 self.assertTrue(D("0.01").is_subnormal(context=xc))
2401
2402 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2403 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2404 self.assertRaises(TypeError, D(1).radix, context=xc)
2405
2406 self.assertEqual(D(-111).logb(context=xc), 2)
2407 self.assertEqual(D(0).logical_invert(context=xc), 1)
2408 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2409 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2410
2411 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2412 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2413 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2414 self.assertEqual(D('23').rotate(1, context=xc), 3)
2415 self.assertEqual(D('23').rotate(1, context=xc), 3)
2416 xc.clear_flags()
2417 self.assertRaises(Overflow,
2418 D('23').scaleb, 1, context=xc)
2419 self.assertTrue(xc.flags[Overflow])
2420 self.assertFalse(c.flags[Overflow])
2421 self.assertEqual(D('23').shift(-1, context=xc), 0)
2422
2423 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2424 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2425
2426 if (self.decimal == C):
2427 self.assertRaises(TypeError, D(1).canonical, context=xc)
2428 self.assertEqual(D("-1").copy_abs(context=xc), 1)
2429 self.assertEqual(D("1").copy_negate(context=xc), -1)
2430 else:
2431 self.assertEqual(D(1).canonical(context=xc), 1)
2432 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2433 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2434
Stefan Krahb6405ef2012-03-23 14:46:48 +01002435 def test_exception_hierarchy(self):
2436
2437 decimal = self.decimal
2438 DecimalException = decimal.DecimalException
2439 InvalidOperation = decimal.InvalidOperation
2440 FloatOperation = decimal.FloatOperation
2441 DivisionByZero = decimal.DivisionByZero
2442 Overflow = decimal.Overflow
2443 Underflow = decimal.Underflow
2444 Subnormal = decimal.Subnormal
2445 Inexact = decimal.Inexact
2446 Rounded = decimal.Rounded
2447 Clamped = decimal.Clamped
2448
2449 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2450
2451 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2452 self.assertTrue(issubclass(FloatOperation, DecimalException))
2453 self.assertTrue(issubclass(FloatOperation, TypeError))
2454 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2455 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2456 self.assertTrue(issubclass(Overflow, Rounded))
2457 self.assertTrue(issubclass(Overflow, Inexact))
2458 self.assertTrue(issubclass(Overflow, DecimalException))
2459 self.assertTrue(issubclass(Underflow, Inexact))
2460 self.assertTrue(issubclass(Underflow, Rounded))
2461 self.assertTrue(issubclass(Underflow, Subnormal))
2462 self.assertTrue(issubclass(Underflow, DecimalException))
2463
2464 self.assertTrue(issubclass(Subnormal, DecimalException))
2465 self.assertTrue(issubclass(Inexact, DecimalException))
2466 self.assertTrue(issubclass(Rounded, DecimalException))
2467 self.assertTrue(issubclass(Clamped, DecimalException))
2468
2469 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2470 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2471 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2472 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2473 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2474
Stefan Krah1919b7e2012-03-21 18:25:23 +01002475class CPythonAPItests(PythonAPItests):
2476 decimal = C
2477class PyPythonAPItests(PythonAPItests):
2478 decimal = P
2479
2480class ContextAPItests(unittest.TestCase):
2481
2482 def test_pickle(self):
2483
2484 Context = self.decimal.Context
2485
2486 savedecimal = sys.modules['decimal']
2487
2488 # Round trip
2489 sys.modules['decimal'] = self.decimal
2490 c = Context()
2491 e = pickle.loads(pickle.dumps(c))
2492
2493 self.assertEqual(c.prec, e.prec)
2494 self.assertEqual(c.Emin, e.Emin)
2495 self.assertEqual(c.Emax, e.Emax)
2496 self.assertEqual(c.rounding, e.rounding)
2497 self.assertEqual(c.capitals, e.capitals)
2498 self.assertEqual(c.clamp, e.clamp)
2499 self.assertEqual(c.flags, e.flags)
2500 self.assertEqual(c.traps, e.traps)
2501
2502 # Test interchangeability
2503 combinations = [(C, P), (P, C)] if C else [(P, P)]
2504 for dumper, loader in combinations:
2505 for ri, _ in enumerate(RoundingModes[dumper]):
2506 for fi, _ in enumerate(OrderedSignals[dumper]):
2507 for ti, _ in enumerate(OrderedSignals[dumper]):
2508
2509 prec = random.randrange(1, 100)
2510 emin = random.randrange(-100, 0)
2511 emax = random.randrange(1, 100)
2512 caps = random.randrange(2)
2513 clamp = random.randrange(2)
2514
2515 # One module dumps
2516 sys.modules['decimal'] = dumper
2517 c = dumper.Context(
2518 prec=prec, Emin=emin, Emax=emax,
2519 rounding=RoundingModes[dumper][ri],
2520 capitals=caps, clamp=clamp,
2521 flags=OrderedSignals[dumper][:fi],
2522 traps=OrderedSignals[dumper][:ti]
2523 )
2524 s = pickle.dumps(c)
2525
2526 # The other module loads
2527 sys.modules['decimal'] = loader
2528 d = pickle.loads(s)
2529 self.assertIsInstance(d, loader.Context)
2530
2531 self.assertEqual(d.prec, prec)
2532 self.assertEqual(d.Emin, emin)
2533 self.assertEqual(d.Emax, emax)
2534 self.assertEqual(d.rounding, RoundingModes[loader][ri])
2535 self.assertEqual(d.capitals, caps)
2536 self.assertEqual(d.clamp, clamp)
2537 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2538 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2539
2540 sys.modules['decimal'] = savedecimal
2541
2542 def test_equality_with_other_types(self):
2543 Decimal = self.decimal.Decimal
2544
2545 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2546 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2547
2548 def test_copy(self):
2549 # All copies should be deep
2550 Decimal = self.decimal.Decimal
2551 Context = self.decimal.Context
2552
2553 c = Context()
2554 d = c.copy()
2555 self.assertNotEqual(id(c), id(d))
2556 self.assertNotEqual(id(c.flags), id(d.flags))
2557 self.assertNotEqual(id(c.traps), id(d.traps))
2558 k1 = set(c.flags.keys())
2559 k2 = set(d.flags.keys())
2560 self.assertEqual(k1, k2)
2561 self.assertEqual(c.flags, d.flags)
2562
2563 def test__clamp(self):
2564 # In Python 3.2, the private attribute `_clamp` was made
2565 # public (issue 8540), with the old `_clamp` becoming a
2566 # property wrapping `clamp`. For the duration of Python 3.2
2567 # only, the attribute should be gettable/settable via both
2568 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2569 # removed.
2570 Context = self.decimal.Context
2571 c = Context()
2572 self.assertRaises(AttributeError, getattr, c, '_clamp')
2573
2574 def test_abs(self):
2575 Decimal = self.decimal.Decimal
2576 Context = self.decimal.Context
2577
2578 c = Context()
2579 d = c.abs(Decimal(-1))
2580 self.assertEqual(c.abs(-1), d)
2581 self.assertRaises(TypeError, c.abs, '-1')
2582
2583 def test_add(self):
2584 Decimal = self.decimal.Decimal
2585 Context = self.decimal.Context
2586
2587 c = Context()
2588 d = c.add(Decimal(1), Decimal(1))
2589 self.assertEqual(c.add(1, 1), d)
2590 self.assertEqual(c.add(Decimal(1), 1), d)
2591 self.assertEqual(c.add(1, Decimal(1)), d)
2592 self.assertRaises(TypeError, c.add, '1', 1)
2593 self.assertRaises(TypeError, c.add, 1, '1')
2594
2595 def test_compare(self):
2596 Decimal = self.decimal.Decimal
2597 Context = self.decimal.Context
2598
2599 c = Context()
2600 d = c.compare(Decimal(1), Decimal(1))
2601 self.assertEqual(c.compare(1, 1), d)
2602 self.assertEqual(c.compare(Decimal(1), 1), d)
2603 self.assertEqual(c.compare(1, Decimal(1)), d)
2604 self.assertRaises(TypeError, c.compare, '1', 1)
2605 self.assertRaises(TypeError, c.compare, 1, '1')
2606
2607 def test_compare_signal(self):
2608 Decimal = self.decimal.Decimal
2609 Context = self.decimal.Context
2610
2611 c = Context()
2612 d = c.compare_signal(Decimal(1), Decimal(1))
2613 self.assertEqual(c.compare_signal(1, 1), d)
2614 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2615 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2616 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2617 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2618
2619 def test_compare_total(self):
2620 Decimal = self.decimal.Decimal
2621 Context = self.decimal.Context
2622
2623 c = Context()
2624 d = c.compare_total(Decimal(1), Decimal(1))
2625 self.assertEqual(c.compare_total(1, 1), d)
2626 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2627 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2628 self.assertRaises(TypeError, c.compare_total, '1', 1)
2629 self.assertRaises(TypeError, c.compare_total, 1, '1')
2630
2631 def test_compare_total_mag(self):
2632 Decimal = self.decimal.Decimal
2633 Context = self.decimal.Context
2634
2635 c = Context()
2636 d = c.compare_total_mag(Decimal(1), Decimal(1))
2637 self.assertEqual(c.compare_total_mag(1, 1), d)
2638 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2639 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2640 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2641 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2642
2643 def test_copy_abs(self):
2644 Decimal = self.decimal.Decimal
2645 Context = self.decimal.Context
2646
2647 c = Context()
2648 d = c.copy_abs(Decimal(-1))
2649 self.assertEqual(c.copy_abs(-1), d)
2650 self.assertRaises(TypeError, c.copy_abs, '-1')
2651
2652 def test_copy_decimal(self):
2653 Decimal = self.decimal.Decimal
2654 Context = self.decimal.Context
2655
2656 c = Context()
2657 d = c.copy_decimal(Decimal(-1))
2658 self.assertEqual(c.copy_decimal(-1), d)
2659 self.assertRaises(TypeError, c.copy_decimal, '-1')
2660
2661 def test_copy_negate(self):
2662 Decimal = self.decimal.Decimal
2663 Context = self.decimal.Context
2664
2665 c = Context()
2666 d = c.copy_negate(Decimal(-1))
2667 self.assertEqual(c.copy_negate(-1), d)
2668 self.assertRaises(TypeError, c.copy_negate, '-1')
2669
2670 def test_copy_sign(self):
2671 Decimal = self.decimal.Decimal
2672 Context = self.decimal.Context
2673
2674 c = Context()
2675 d = c.copy_sign(Decimal(1), Decimal(-2))
2676 self.assertEqual(c.copy_sign(1, -2), d)
2677 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2678 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2679 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2680 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2681
2682 def test_divide(self):
2683 Decimal = self.decimal.Decimal
2684 Context = self.decimal.Context
2685
2686 c = Context()
2687 d = c.divide(Decimal(1), Decimal(2))
2688 self.assertEqual(c.divide(1, 2), d)
2689 self.assertEqual(c.divide(Decimal(1), 2), d)
2690 self.assertEqual(c.divide(1, Decimal(2)), d)
2691 self.assertRaises(TypeError, c.divide, '1', 2)
2692 self.assertRaises(TypeError, c.divide, 1, '2')
2693
2694 def test_divide_int(self):
2695 Decimal = self.decimal.Decimal
2696 Context = self.decimal.Context
2697
2698 c = Context()
2699 d = c.divide_int(Decimal(1), Decimal(2))
2700 self.assertEqual(c.divide_int(1, 2), d)
2701 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2702 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2703 self.assertRaises(TypeError, c.divide_int, '1', 2)
2704 self.assertRaises(TypeError, c.divide_int, 1, '2')
2705
2706 def test_divmod(self):
2707 Decimal = self.decimal.Decimal
2708 Context = self.decimal.Context
2709
2710 c = Context()
2711 d = c.divmod(Decimal(1), Decimal(2))
2712 self.assertEqual(c.divmod(1, 2), d)
2713 self.assertEqual(c.divmod(Decimal(1), 2), d)
2714 self.assertEqual(c.divmod(1, Decimal(2)), d)
2715 self.assertRaises(TypeError, c.divmod, '1', 2)
2716 self.assertRaises(TypeError, c.divmod, 1, '2')
2717
2718 def test_exp(self):
2719 Decimal = self.decimal.Decimal
2720 Context = self.decimal.Context
2721
2722 c = Context()
2723 d = c.exp(Decimal(10))
2724 self.assertEqual(c.exp(10), d)
2725 self.assertRaises(TypeError, c.exp, '10')
2726
2727 def test_fma(self):
2728 Decimal = self.decimal.Decimal
2729 Context = self.decimal.Context
2730
2731 c = Context()
2732 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
2733 self.assertEqual(c.fma(2, 3, 4), d)
2734 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
2735 self.assertEqual(c.fma(2, Decimal(3), 4), d)
2736 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
2737 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
2738 self.assertRaises(TypeError, c.fma, '2', 3, 4)
2739 self.assertRaises(TypeError, c.fma, 2, '3', 4)
2740 self.assertRaises(TypeError, c.fma, 2, 3, '4')
2741
2742 # Issue 12079 for Context.fma ...
2743 self.assertRaises(TypeError, c.fma,
2744 Decimal('Infinity'), Decimal(0), "not a decimal")
2745 self.assertRaises(TypeError, c.fma,
2746 Decimal(1), Decimal('snan'), 1.222)
2747 # ... and for Decimal.fma.
2748 self.assertRaises(TypeError, Decimal('Infinity').fma,
2749 Decimal(0), "not a decimal")
2750 self.assertRaises(TypeError, Decimal(1).fma,
2751 Decimal('snan'), 1.222)
2752
2753 def test_is_finite(self):
2754 Decimal = self.decimal.Decimal
2755 Context = self.decimal.Context
2756
2757 c = Context()
2758 d = c.is_finite(Decimal(10))
2759 self.assertEqual(c.is_finite(10), d)
2760 self.assertRaises(TypeError, c.is_finite, '10')
2761
2762 def test_is_infinite(self):
2763 Decimal = self.decimal.Decimal
2764 Context = self.decimal.Context
2765
2766 c = Context()
2767 d = c.is_infinite(Decimal(10))
2768 self.assertEqual(c.is_infinite(10), d)
2769 self.assertRaises(TypeError, c.is_infinite, '10')
2770
2771 def test_is_nan(self):
2772 Decimal = self.decimal.Decimal
2773 Context = self.decimal.Context
2774
2775 c = Context()
2776 d = c.is_nan(Decimal(10))
2777 self.assertEqual(c.is_nan(10), d)
2778 self.assertRaises(TypeError, c.is_nan, '10')
2779
2780 def test_is_normal(self):
2781 Decimal = self.decimal.Decimal
2782 Context = self.decimal.Context
2783
2784 c = Context()
2785 d = c.is_normal(Decimal(10))
2786 self.assertEqual(c.is_normal(10), d)
2787 self.assertRaises(TypeError, c.is_normal, '10')
2788
2789 def test_is_qnan(self):
2790 Decimal = self.decimal.Decimal
2791 Context = self.decimal.Context
2792
2793 c = Context()
2794 d = c.is_qnan(Decimal(10))
2795 self.assertEqual(c.is_qnan(10), d)
2796 self.assertRaises(TypeError, c.is_qnan, '10')
2797
2798 def test_is_signed(self):
2799 Decimal = self.decimal.Decimal
2800 Context = self.decimal.Context
2801
2802 c = Context()
2803 d = c.is_signed(Decimal(10))
2804 self.assertEqual(c.is_signed(10), d)
2805 self.assertRaises(TypeError, c.is_signed, '10')
2806
2807 def test_is_snan(self):
2808 Decimal = self.decimal.Decimal
2809 Context = self.decimal.Context
2810
2811 c = Context()
2812 d = c.is_snan(Decimal(10))
2813 self.assertEqual(c.is_snan(10), d)
2814 self.assertRaises(TypeError, c.is_snan, '10')
2815
2816 def test_is_subnormal(self):
2817 Decimal = self.decimal.Decimal
2818 Context = self.decimal.Context
2819
2820 c = Context()
2821 d = c.is_subnormal(Decimal(10))
2822 self.assertEqual(c.is_subnormal(10), d)
2823 self.assertRaises(TypeError, c.is_subnormal, '10')
2824
2825 def test_is_zero(self):
2826 Decimal = self.decimal.Decimal
2827 Context = self.decimal.Context
2828
2829 c = Context()
2830 d = c.is_zero(Decimal(10))
2831 self.assertEqual(c.is_zero(10), d)
2832 self.assertRaises(TypeError, c.is_zero, '10')
2833
2834 def test_ln(self):
2835 Decimal = self.decimal.Decimal
2836 Context = self.decimal.Context
2837
2838 c = Context()
2839 d = c.ln(Decimal(10))
2840 self.assertEqual(c.ln(10), d)
2841 self.assertRaises(TypeError, c.ln, '10')
2842
2843 def test_log10(self):
2844 Decimal = self.decimal.Decimal
2845 Context = self.decimal.Context
2846
2847 c = Context()
2848 d = c.log10(Decimal(10))
2849 self.assertEqual(c.log10(10), d)
2850 self.assertRaises(TypeError, c.log10, '10')
2851
2852 def test_logb(self):
2853 Decimal = self.decimal.Decimal
2854 Context = self.decimal.Context
2855
2856 c = Context()
2857 d = c.logb(Decimal(10))
2858 self.assertEqual(c.logb(10), d)
2859 self.assertRaises(TypeError, c.logb, '10')
2860
2861 def test_logical_and(self):
2862 Decimal = self.decimal.Decimal
2863 Context = self.decimal.Context
2864
2865 c = Context()
2866 d = c.logical_and(Decimal(1), Decimal(1))
2867 self.assertEqual(c.logical_and(1, 1), d)
2868 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2869 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2870 self.assertRaises(TypeError, c.logical_and, '1', 1)
2871 self.assertRaises(TypeError, c.logical_and, 1, '1')
2872
2873 def test_logical_invert(self):
2874 Decimal = self.decimal.Decimal
2875 Context = self.decimal.Context
2876
2877 c = Context()
2878 d = c.logical_invert(Decimal(1000))
2879 self.assertEqual(c.logical_invert(1000), d)
2880 self.assertRaises(TypeError, c.logical_invert, '1000')
2881
2882 def test_logical_or(self):
2883 Decimal = self.decimal.Decimal
2884 Context = self.decimal.Context
2885
2886 c = Context()
2887 d = c.logical_or(Decimal(1), Decimal(1))
2888 self.assertEqual(c.logical_or(1, 1), d)
2889 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2890 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2891 self.assertRaises(TypeError, c.logical_or, '1', 1)
2892 self.assertRaises(TypeError, c.logical_or, 1, '1')
2893
2894 def test_logical_xor(self):
2895 Decimal = self.decimal.Decimal
2896 Context = self.decimal.Context
2897
2898 c = Context()
2899 d = c.logical_xor(Decimal(1), Decimal(1))
2900 self.assertEqual(c.logical_xor(1, 1), d)
2901 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2902 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2903 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2904 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2905
2906 def test_max(self):
2907 Decimal = self.decimal.Decimal
2908 Context = self.decimal.Context
2909
2910 c = Context()
2911 d = c.max(Decimal(1), Decimal(2))
2912 self.assertEqual(c.max(1, 2), d)
2913 self.assertEqual(c.max(Decimal(1), 2), d)
2914 self.assertEqual(c.max(1, Decimal(2)), d)
2915 self.assertRaises(TypeError, c.max, '1', 2)
2916 self.assertRaises(TypeError, c.max, 1, '2')
2917
2918 def test_max_mag(self):
2919 Decimal = self.decimal.Decimal
2920 Context = self.decimal.Context
2921
2922 c = Context()
2923 d = c.max_mag(Decimal(1), Decimal(2))
2924 self.assertEqual(c.max_mag(1, 2), d)
2925 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2926 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2927 self.assertRaises(TypeError, c.max_mag, '1', 2)
2928 self.assertRaises(TypeError, c.max_mag, 1, '2')
2929
2930 def test_min(self):
2931 Decimal = self.decimal.Decimal
2932 Context = self.decimal.Context
2933
2934 c = Context()
2935 d = c.min(Decimal(1), Decimal(2))
2936 self.assertEqual(c.min(1, 2), d)
2937 self.assertEqual(c.min(Decimal(1), 2), d)
2938 self.assertEqual(c.min(1, Decimal(2)), d)
2939 self.assertRaises(TypeError, c.min, '1', 2)
2940 self.assertRaises(TypeError, c.min, 1, '2')
2941
2942 def test_min_mag(self):
2943 Decimal = self.decimal.Decimal
2944 Context = self.decimal.Context
2945
2946 c = Context()
2947 d = c.min_mag(Decimal(1), Decimal(2))
2948 self.assertEqual(c.min_mag(1, 2), d)
2949 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2950 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2951 self.assertRaises(TypeError, c.min_mag, '1', 2)
2952 self.assertRaises(TypeError, c.min_mag, 1, '2')
2953
2954 def test_minus(self):
2955 Decimal = self.decimal.Decimal
2956 Context = self.decimal.Context
2957
2958 c = Context()
2959 d = c.minus(Decimal(10))
2960 self.assertEqual(c.minus(10), d)
2961 self.assertRaises(TypeError, c.minus, '10')
2962
2963 def test_multiply(self):
2964 Decimal = self.decimal.Decimal
2965 Context = self.decimal.Context
2966
2967 c = Context()
2968 d = c.multiply(Decimal(1), Decimal(2))
2969 self.assertEqual(c.multiply(1, 2), d)
2970 self.assertEqual(c.multiply(Decimal(1), 2), d)
2971 self.assertEqual(c.multiply(1, Decimal(2)), d)
2972 self.assertRaises(TypeError, c.multiply, '1', 2)
2973 self.assertRaises(TypeError, c.multiply, 1, '2')
2974
2975 def test_next_minus(self):
2976 Decimal = self.decimal.Decimal
2977 Context = self.decimal.Context
2978
2979 c = Context()
2980 d = c.next_minus(Decimal(10))
2981 self.assertEqual(c.next_minus(10), d)
2982 self.assertRaises(TypeError, c.next_minus, '10')
2983
2984 def test_next_plus(self):
2985 Decimal = self.decimal.Decimal
2986 Context = self.decimal.Context
2987
2988 c = Context()
2989 d = c.next_plus(Decimal(10))
2990 self.assertEqual(c.next_plus(10), d)
2991 self.assertRaises(TypeError, c.next_plus, '10')
2992
2993 def test_next_toward(self):
2994 Decimal = self.decimal.Decimal
2995 Context = self.decimal.Context
2996
2997 c = Context()
2998 d = c.next_toward(Decimal(1), Decimal(2))
2999 self.assertEqual(c.next_toward(1, 2), d)
3000 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3001 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3002 self.assertRaises(TypeError, c.next_toward, '1', 2)
3003 self.assertRaises(TypeError, c.next_toward, 1, '2')
3004
3005 def test_normalize(self):
3006 Decimal = self.decimal.Decimal
3007 Context = self.decimal.Context
3008
3009 c = Context()
3010 d = c.normalize(Decimal(10))
3011 self.assertEqual(c.normalize(10), d)
3012 self.assertRaises(TypeError, c.normalize, '10')
3013
3014 def test_number_class(self):
3015 Decimal = self.decimal.Decimal
3016 Context = self.decimal.Context
3017
3018 c = Context()
3019 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3020 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3021 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3022
3023 def test_plus(self):
3024 Decimal = self.decimal.Decimal
3025 Context = self.decimal.Context
3026
3027 c = Context()
3028 d = c.plus(Decimal(10))
3029 self.assertEqual(c.plus(10), d)
3030 self.assertRaises(TypeError, c.plus, '10')
3031
3032 def test_power(self):
3033 Decimal = self.decimal.Decimal
3034 Context = self.decimal.Context
3035
3036 c = Context()
3037 d = c.power(Decimal(1), Decimal(4))
3038 self.assertEqual(c.power(1, 4), d)
3039 self.assertEqual(c.power(Decimal(1), 4), d)
3040 self.assertEqual(c.power(1, Decimal(4)), d)
3041 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3042 self.assertRaises(TypeError, c.power, '1', 4)
3043 self.assertRaises(TypeError, c.power, 1, '4')
3044 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3045
3046 def test_quantize(self):
3047 Decimal = self.decimal.Decimal
3048 Context = self.decimal.Context
3049
3050 c = Context()
3051 d = c.quantize(Decimal(1), Decimal(2))
3052 self.assertEqual(c.quantize(1, 2), d)
3053 self.assertEqual(c.quantize(Decimal(1), 2), d)
3054 self.assertEqual(c.quantize(1, Decimal(2)), d)
3055 self.assertRaises(TypeError, c.quantize, '1', 2)
3056 self.assertRaises(TypeError, c.quantize, 1, '2')
3057
3058 def test_remainder(self):
3059 Decimal = self.decimal.Decimal
3060 Context = self.decimal.Context
3061
3062 c = Context()
3063 d = c.remainder(Decimal(1), Decimal(2))
3064 self.assertEqual(c.remainder(1, 2), d)
3065 self.assertEqual(c.remainder(Decimal(1), 2), d)
3066 self.assertEqual(c.remainder(1, Decimal(2)), d)
3067 self.assertRaises(TypeError, c.remainder, '1', 2)
3068 self.assertRaises(TypeError, c.remainder, 1, '2')
3069
3070 def test_remainder_near(self):
3071 Decimal = self.decimal.Decimal
3072 Context = self.decimal.Context
3073
3074 c = Context()
3075 d = c.remainder_near(Decimal(1), Decimal(2))
3076 self.assertEqual(c.remainder_near(1, 2), d)
3077 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3078 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3079 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3080 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3081
3082 def test_rotate(self):
3083 Decimal = self.decimal.Decimal
3084 Context = self.decimal.Context
3085
3086 c = Context()
3087 d = c.rotate(Decimal(1), Decimal(2))
3088 self.assertEqual(c.rotate(1, 2), d)
3089 self.assertEqual(c.rotate(Decimal(1), 2), d)
3090 self.assertEqual(c.rotate(1, Decimal(2)), d)
3091 self.assertRaises(TypeError, c.rotate, '1', 2)
3092 self.assertRaises(TypeError, c.rotate, 1, '2')
3093
3094 def test_sqrt(self):
3095 Decimal = self.decimal.Decimal
3096 Context = self.decimal.Context
3097
3098 c = Context()
3099 d = c.sqrt(Decimal(10))
3100 self.assertEqual(c.sqrt(10), d)
3101 self.assertRaises(TypeError, c.sqrt, '10')
3102
3103 def test_same_quantum(self):
3104 Decimal = self.decimal.Decimal
3105 Context = self.decimal.Context
3106
3107 c = Context()
3108 d = c.same_quantum(Decimal(1), Decimal(2))
3109 self.assertEqual(c.same_quantum(1, 2), d)
3110 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3111 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3112 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3113 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3114
3115 def test_scaleb(self):
3116 Decimal = self.decimal.Decimal
3117 Context = self.decimal.Context
3118
3119 c = Context()
3120 d = c.scaleb(Decimal(1), Decimal(2))
3121 self.assertEqual(c.scaleb(1, 2), d)
3122 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3123 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3124 self.assertRaises(TypeError, c.scaleb, '1', 2)
3125 self.assertRaises(TypeError, c.scaleb, 1, '2')
3126
3127 def test_shift(self):
3128 Decimal = self.decimal.Decimal
3129 Context = self.decimal.Context
3130
3131 c = Context()
3132 d = c.shift(Decimal(1), Decimal(2))
3133 self.assertEqual(c.shift(1, 2), d)
3134 self.assertEqual(c.shift(Decimal(1), 2), d)
3135 self.assertEqual(c.shift(1, Decimal(2)), d)
3136 self.assertRaises(TypeError, c.shift, '1', 2)
3137 self.assertRaises(TypeError, c.shift, 1, '2')
3138
3139 def test_subtract(self):
3140 Decimal = self.decimal.Decimal
3141 Context = self.decimal.Context
3142
3143 c = Context()
3144 d = c.subtract(Decimal(1), Decimal(2))
3145 self.assertEqual(c.subtract(1, 2), d)
3146 self.assertEqual(c.subtract(Decimal(1), 2), d)
3147 self.assertEqual(c.subtract(1, Decimal(2)), d)
3148 self.assertRaises(TypeError, c.subtract, '1', 2)
3149 self.assertRaises(TypeError, c.subtract, 1, '2')
3150
3151 def test_to_eng_string(self):
3152 Decimal = self.decimal.Decimal
3153 Context = self.decimal.Context
3154
3155 c = Context()
3156 d = c.to_eng_string(Decimal(10))
3157 self.assertEqual(c.to_eng_string(10), d)
3158 self.assertRaises(TypeError, c.to_eng_string, '10')
3159
3160 def test_to_sci_string(self):
3161 Decimal = self.decimal.Decimal
3162 Context = self.decimal.Context
3163
3164 c = Context()
3165 d = c.to_sci_string(Decimal(10))
3166 self.assertEqual(c.to_sci_string(10), d)
3167 self.assertRaises(TypeError, c.to_sci_string, '10')
3168
3169 def test_to_integral_exact(self):
3170 Decimal = self.decimal.Decimal
3171 Context = self.decimal.Context
3172
3173 c = Context()
3174 d = c.to_integral_exact(Decimal(10))
3175 self.assertEqual(c.to_integral_exact(10), d)
3176 self.assertRaises(TypeError, c.to_integral_exact, '10')
3177
3178 def test_to_integral_value(self):
3179 Decimal = self.decimal.Decimal
3180 Context = self.decimal.Context
3181
3182 c = Context()
3183 d = c.to_integral_value(Decimal(10))
3184 self.assertEqual(c.to_integral_value(10), d)
3185 self.assertRaises(TypeError, c.to_integral_value, '10')
3186 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3187
3188class CContextAPItests(ContextAPItests):
3189 decimal = C
3190class PyContextAPItests(ContextAPItests):
3191 decimal = P
3192
3193class ContextWithStatement(unittest.TestCase):
3194 # Can't do these as docstrings until Python 2.6
3195 # as doctest can't handle __future__ statements
3196
3197 def test_localcontext(self):
3198 # Use a copy of the current context in the block
3199 getcontext = self.decimal.getcontext
3200 localcontext = self.decimal.localcontext
3201
3202 orig_ctx = getcontext()
3203 with localcontext() as enter_ctx:
3204 set_ctx = getcontext()
3205 final_ctx = getcontext()
3206 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3207 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3208 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3209
3210 def test_localcontextarg(self):
3211 # Use a copy of the supplied context in the block
3212 Context = self.decimal.Context
3213 getcontext = self.decimal.getcontext
3214 localcontext = self.decimal.localcontext
3215
3216 localcontext = self.decimal.localcontext
3217 orig_ctx = getcontext()
3218 new_ctx = Context(prec=42)
3219 with localcontext(new_ctx) as enter_ctx:
3220 set_ctx = getcontext()
3221 final_ctx = getcontext()
3222 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3223 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3224 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3225 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3226
3227 def test_nested_with_statements(self):
3228 # Use a copy of the supplied context in the block
3229 Decimal = self.decimal.Decimal
3230 Context = self.decimal.Context
3231 getcontext = self.decimal.getcontext
3232 localcontext = self.decimal.localcontext
3233 Clamped = self.decimal.Clamped
3234 Overflow = self.decimal.Overflow
3235
3236 orig_ctx = getcontext()
3237 orig_ctx.clear_flags()
3238 new_ctx = Context(Emax=384)
3239 with localcontext() as c1:
3240 self.assertEqual(c1.flags, orig_ctx.flags)
3241 self.assertEqual(c1.traps, orig_ctx.traps)
3242 c1.traps[Clamped] = True
3243 c1.Emin = -383
3244 self.assertNotEqual(orig_ctx.Emin, -383)
3245 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3246 self.assertTrue(c1.flags[Clamped])
3247 with localcontext(new_ctx) as c2:
3248 self.assertEqual(c2.flags, new_ctx.flags)
3249 self.assertEqual(c2.traps, new_ctx.traps)
3250 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3251 self.assertFalse(c2.flags[Clamped])
3252 self.assertTrue(c2.flags[Overflow])
3253 del c2
3254 self.assertFalse(c1.flags[Overflow])
3255 del c1
3256 self.assertNotEqual(orig_ctx.Emin, -383)
3257 self.assertFalse(orig_ctx.flags[Clamped])
3258 self.assertFalse(orig_ctx.flags[Overflow])
3259 self.assertFalse(new_ctx.flags[Clamped])
3260 self.assertFalse(new_ctx.flags[Overflow])
3261
3262 def test_with_statements_gc1(self):
3263 localcontext = self.decimal.localcontext
3264
3265 with localcontext() as c1:
3266 del c1
3267 with localcontext() as c2:
3268 del c2
3269 with localcontext() as c3:
3270 del c3
3271 with localcontext() as c4:
3272 del c4
3273
3274 def test_with_statements_gc2(self):
3275 localcontext = self.decimal.localcontext
3276
3277 with localcontext() as c1:
3278 with localcontext(c1) as c2:
3279 del c1
3280 with localcontext(c2) as c3:
3281 del c2
3282 with localcontext(c3) as c4:
3283 del c3
3284 del c4
3285
3286 def test_with_statements_gc3(self):
3287 Context = self.decimal.Context
3288 localcontext = self.decimal.localcontext
3289 getcontext = self.decimal.getcontext
3290 setcontext = self.decimal.setcontext
3291
3292 with localcontext() as c1:
3293 del c1
3294 n1 = Context(prec=1)
3295 setcontext(n1)
3296 with localcontext(n1) as c2:
3297 del n1
3298 self.assertEqual(c2.prec, 1)
3299 del c2
3300 n2 = Context(prec=2)
3301 setcontext(n2)
3302 del n2
3303 self.assertEqual(getcontext().prec, 2)
3304 n3 = Context(prec=3)
3305 setcontext(n3)
3306 self.assertEqual(getcontext().prec, 3)
3307 with localcontext(n3) as c3:
3308 del n3
3309 self.assertEqual(c3.prec, 3)
3310 del c3
3311 n4 = Context(prec=4)
3312 setcontext(n4)
3313 del n4
3314 self.assertEqual(getcontext().prec, 4)
3315 with localcontext() as c4:
3316 self.assertEqual(c4.prec, 4)
3317 del c4
3318
3319class CContextWithStatement(ContextWithStatement):
3320 decimal = C
3321class PyContextWithStatement(ContextWithStatement):
3322 decimal = P
3323
3324class ContextFlags(unittest.TestCase):
3325
3326 def test_flags_irrelevant(self):
3327 # check that the result (numeric result + flags raised) of an
3328 # arithmetic operation doesn't depend on the current flags
3329 Decimal = self.decimal.Decimal
3330 Context = self.decimal.Context
3331 Inexact = self.decimal.Inexact
3332 Rounded = self.decimal.Rounded
3333 Underflow = self.decimal.Underflow
3334 Clamped = self.decimal.Clamped
3335 Subnormal = self.decimal.Subnormal
3336 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
3337
3338 def raise_error(context, flag):
3339 if self.decimal == C:
3340 context.flags[flag] = True
3341 if context.traps[flag]:
3342 raise flag
3343 else:
3344 context._raise_error(flag)
3345
3346 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3347 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3348
3349 # operations that raise various flags, in the form (function, arglist)
3350 operations = [
3351 (context._apply, [Decimal("100E-425000010")]),
3352 (context.sqrt, [Decimal(2)]),
3353 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3354 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3355 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3356 ]
3357
3358 # try various flags individually, then a whole lot at once
3359 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3360 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3361
3362 for fn, args in operations:
3363 # find answer and flags raised using a clean context
3364 context.clear_flags()
3365 ans = fn(*args)
3366 flags = [k for k, v in context.flags.items() if v]
3367
3368 for extra_flags in flagsets:
3369 # set flags, before calling operation
3370 context.clear_flags()
3371 for flag in extra_flags:
3372 raise_error(context, flag)
3373 new_ans = fn(*args)
3374
3375 # flags that we expect to be set after the operation
3376 expected_flags = list(flags)
3377 for flag in extra_flags:
3378 if flag not in expected_flags:
3379 expected_flags.append(flag)
3380 expected_flags.sort(key=id)
3381
3382 # flags we actually got
3383 new_flags = [k for k,v in context.flags.items() if v]
3384 new_flags.sort(key=id)
3385
3386 self.assertEqual(ans, new_ans,
3387 "operation produces different answers depending on flags set: " +
3388 "expected %s, got %s." % (ans, new_ans))
3389 self.assertEqual(new_flags, expected_flags,
3390 "operation raises different flags depending on flags set: " +
3391 "expected %s, got %s" % (expected_flags, new_flags))
3392
3393 def test_flag_comparisons(self):
3394 Context = self.decimal.Context
3395 Inexact = self.decimal.Inexact
3396 Rounded = self.decimal.Rounded
3397
3398 c = Context()
3399
3400 # Valid SignalDict
3401 self.assertNotEqual(c.flags, c.traps)
3402 self.assertNotEqual(c.traps, c.flags)
3403
3404 c.flags = c.traps
3405 self.assertEqual(c.flags, c.traps)
3406 self.assertEqual(c.traps, c.flags)
3407
3408 c.flags[Rounded] = True
3409 c.traps = c.flags
3410 self.assertEqual(c.flags, c.traps)
3411 self.assertEqual(c.traps, c.flags)
3412
3413 d = {}
3414 d.update(c.flags)
3415 self.assertEqual(d, c.flags)
3416 self.assertEqual(c.flags, d)
3417
3418 d[Inexact] = True
3419 self.assertNotEqual(d, c.flags)
3420 self.assertNotEqual(c.flags, d)
3421
3422 # Invalid SignalDict
3423 d = {Inexact:False}
3424 self.assertNotEqual(d, c.flags)
3425 self.assertNotEqual(c.flags, d)
3426
3427 d = ["xyz"]
3428 self.assertNotEqual(d, c.flags)
3429 self.assertNotEqual(c.flags, d)
3430
3431 @requires_IEEE_754
3432 def test_float_operation(self):
3433 Decimal = self.decimal.Decimal
3434 FloatOperation = self.decimal.FloatOperation
3435 localcontext = self.decimal.localcontext
3436
3437 with localcontext() as c:
3438 ##### trap is off by default
3439 self.assertFalse(c.traps[FloatOperation])
3440
3441 # implicit conversion sets the flag
3442 c.clear_flags()
3443 self.assertEqual(Decimal(7.5), 7.5)
3444 self.assertTrue(c.flags[FloatOperation])
3445
3446 c.clear_flags()
3447 self.assertEqual(c.create_decimal(7.5), 7.5)
3448 self.assertTrue(c.flags[FloatOperation])
3449
3450 # explicit conversion does not set the flag
3451 c.clear_flags()
3452 x = Decimal.from_float(7.5)
3453 self.assertFalse(c.flags[FloatOperation])
3454 # comparison sets the flag
3455 self.assertEqual(x, 7.5)
3456 self.assertTrue(c.flags[FloatOperation])
3457
3458 c.clear_flags()
3459 x = c.create_decimal_from_float(7.5)
3460 self.assertFalse(c.flags[FloatOperation])
3461 self.assertEqual(x, 7.5)
3462 self.assertTrue(c.flags[FloatOperation])
3463
3464 ##### set the trap
3465 c.traps[FloatOperation] = True
3466
3467 # implicit conversion raises
3468 c.clear_flags()
3469 self.assertRaises(FloatOperation, Decimal, 7.5)
3470 self.assertTrue(c.flags[FloatOperation])
3471
3472 c.clear_flags()
3473 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3474 self.assertTrue(c.flags[FloatOperation])
3475
3476 # explicit conversion is silent
3477 c.clear_flags()
3478 x = Decimal.from_float(7.5)
3479 self.assertFalse(c.flags[FloatOperation])
3480
3481 c.clear_flags()
3482 x = c.create_decimal_from_float(7.5)
3483 self.assertFalse(c.flags[FloatOperation])
3484
3485 def test_float_comparison(self):
3486 Decimal = self.decimal.Decimal
3487 Context = self.decimal.Context
3488 FloatOperation = self.decimal.FloatOperation
3489 localcontext = self.decimal.localcontext
3490
3491 def assert_attr(a, b, attr, context, signal=None):
3492 context.clear_flags()
3493 f = getattr(a, attr)
3494 if signal == FloatOperation:
3495 self.assertRaises(signal, f, b)
3496 else:
3497 self.assertIs(f(b), True)
3498 self.assertTrue(context.flags[FloatOperation])
3499
3500 small_d = Decimal('0.25')
3501 big_d = Decimal('3.0')
3502 small_f = 0.25
3503 big_f = 3.0
3504
3505 zero_d = Decimal('0.0')
3506 neg_zero_d = Decimal('-0.0')
3507 zero_f = 0.0
3508 neg_zero_f = -0.0
3509
3510 inf_d = Decimal('Infinity')
3511 neg_inf_d = Decimal('-Infinity')
3512 inf_f = float('inf')
3513 neg_inf_f = float('-inf')
3514
3515 def doit(c, signal=None):
3516 # Order
3517 for attr in '__lt__', '__le__':
3518 assert_attr(small_d, big_f, attr, c, signal)
3519
3520 for attr in '__gt__', '__ge__':
3521 assert_attr(big_d, small_f, attr, c, signal)
3522
3523 # Equality
3524 assert_attr(small_d, small_f, '__eq__', c, None)
3525
3526 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3527 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3528
3529 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3530 assert_attr(zero_d, zero_f, '__eq__', c, None)
3531
3532 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3533 assert_attr(inf_d, inf_f, '__eq__', c, None)
3534
3535 # Inequality
3536 assert_attr(small_d, big_f, '__ne__', c, None)
3537
3538 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3539
3540 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3541 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3542
3543 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3544
3545 def test_containers(c, signal=None):
3546 c.clear_flags()
3547 s = set([100.0, Decimal('100.0')])
3548 self.assertEqual(len(s), 1)
3549 self.assertTrue(c.flags[FloatOperation])
3550
3551 c.clear_flags()
3552 if signal:
3553 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3554 else:
3555 s = sorted([10.0, Decimal('10.0')])
3556 self.assertTrue(c.flags[FloatOperation])
3557
3558 c.clear_flags()
3559 b = 10.0 in [Decimal('10.0'), 1.0]
3560 self.assertTrue(c.flags[FloatOperation])
3561
3562 c.clear_flags()
3563 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3564 self.assertTrue(c.flags[FloatOperation])
3565
3566 nc = Context()
3567 with localcontext(nc) as c:
3568 self.assertFalse(c.traps[FloatOperation])
3569 doit(c, signal=None)
3570 test_containers(c, signal=None)
3571
3572 c.traps[FloatOperation] = True
3573 doit(c, signal=FloatOperation)
3574 test_containers(c, signal=FloatOperation)
3575
3576 def test_float_operation_default(self):
3577 Decimal = self.decimal.Decimal
3578 Context = self.decimal.Context
3579 Inexact = self.decimal.Inexact
3580 FloatOperation= self.decimal.FloatOperation
3581
3582 context = Context()
3583 self.assertFalse(context.flags[FloatOperation])
3584 self.assertFalse(context.traps[FloatOperation])
3585
3586 context.clear_traps()
3587 context.traps[Inexact] = True
3588 context.traps[FloatOperation] = True
3589 self.assertTrue(context.traps[FloatOperation])
3590 self.assertTrue(context.traps[Inexact])
3591
3592class CContextFlags(ContextFlags):
3593 decimal = C
3594class PyContextFlags(ContextFlags):
3595 decimal = P
3596
3597class SpecialContexts(unittest.TestCase):
3598 """Test the context templates."""
3599
3600 def test_context_templates(self):
3601 BasicContext = self.decimal.BasicContext
3602 ExtendedContext = self.decimal.ExtendedContext
3603 getcontext = self.decimal.getcontext
3604 setcontext = self.decimal.setcontext
3605 InvalidOperation = self.decimal.InvalidOperation
3606 DivisionByZero = self.decimal.DivisionByZero
3607 Overflow = self.decimal.Overflow
3608 Underflow = self.decimal.Underflow
3609 Clamped = self.decimal.Clamped
3610
3611 assert_signals(self, BasicContext, 'traps',
3612 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3613 )
3614
3615 savecontext = getcontext().copy()
3616 basic_context_prec = BasicContext.prec
3617 extended_context_prec = ExtendedContext.prec
3618
3619 ex = None
3620 try:
3621 BasicContext.prec = ExtendedContext.prec = 441
3622 for template in BasicContext, ExtendedContext:
3623 setcontext(template)
3624 c = getcontext()
3625 self.assertIsNot(c, template)
3626 self.assertEqual(c.prec, 441)
3627 except Exception as e:
3628 ex = e.__class__
3629 finally:
3630 BasicContext.prec = basic_context_prec
3631 ExtendedContext.prec = extended_context_prec
3632 setcontext(savecontext)
3633 if ex:
3634 raise ex
3635
3636 def test_default_context(self):
3637 DefaultContext = self.decimal.DefaultContext
3638 BasicContext = self.decimal.BasicContext
3639 ExtendedContext = self.decimal.ExtendedContext
3640 getcontext = self.decimal.getcontext
3641 setcontext = self.decimal.setcontext
3642 InvalidOperation = self.decimal.InvalidOperation
3643 DivisionByZero = self.decimal.DivisionByZero
3644 Overflow = self.decimal.Overflow
3645
3646 self.assertEqual(BasicContext.prec, 9)
3647 self.assertEqual(ExtendedContext.prec, 9)
3648
3649 assert_signals(self, DefaultContext, 'traps',
3650 [InvalidOperation, DivisionByZero, Overflow]
3651 )
3652
3653 savecontext = getcontext().copy()
3654 default_context_prec = DefaultContext.prec
3655
3656 ex = None
3657 try:
3658 c = getcontext()
3659 saveprec = c.prec
3660
3661 DefaultContext.prec = 961
3662 c = getcontext()
3663 self.assertEqual(c.prec, saveprec)
3664
3665 setcontext(DefaultContext)
3666 c = getcontext()
3667 self.assertIsNot(c, DefaultContext)
3668 self.assertEqual(c.prec, 961)
3669 except Exception as e:
3670 ex = e.__class__
3671 finally:
3672 DefaultContext.prec = default_context_prec
3673 setcontext(savecontext)
3674 if ex:
3675 raise ex
3676
3677class CSpecialContexts(SpecialContexts):
3678 decimal = C
3679class PySpecialContexts(SpecialContexts):
3680 decimal = P
3681
3682class ContextInputValidation(unittest.TestCase):
3683
3684 def test_invalid_context(self):
3685 Context = self.decimal.Context
3686 DefaultContext = self.decimal.DefaultContext
3687
3688 c = DefaultContext.copy()
3689
3690 # prec, Emax
3691 for attr in ['prec', 'Emax']:
3692 setattr(c, attr, 999999)
3693 self.assertEqual(getattr(c, attr), 999999)
3694 self.assertRaises(ValueError, setattr, c, attr, -1)
3695 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3696
3697 # Emin
3698 setattr(c, 'Emin', -999999)
3699 self.assertEqual(getattr(c, 'Emin'), -999999)
3700 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3701 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3702
3703 # rounding: always raise TypeError in order to get consistent
3704 # exceptions across implementations. In decimal, rounding
3705 # modes are strings, in _decimal they are integers. The idea
3706 # is to view rounding as an abstract type and not mind the
3707 # implementation details.
3708 # Hence, a user should view the rounding modes as if they
3709 # had been defined in a language that supports abstract
3710 # data types, e.g. ocaml:
3711 #
3712 # type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;;
3713 #
3714 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3715 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3716 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3717 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3718
3719 # capitals, clamp
3720 for attr in ['capitals', 'clamp']:
3721 self.assertRaises(ValueError, setattr, c, attr, -1)
3722 self.assertRaises(ValueError, setattr, c, attr, 2)
3723 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3724
3725 # Invalid attribute
3726 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3727
3728 # Invalid signal dict
3729 self.assertRaises(TypeError, setattr, c, 'flags', [])
3730 self.assertRaises(KeyError, setattr, c, 'flags', {})
3731 self.assertRaises(KeyError, setattr, c, 'traps',
3732 {'InvalidOperation':0})
3733
3734 # Attributes cannot be deleted
3735 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3736 'flags', 'traps']:
3737 self.assertRaises(AttributeError, c.__delattr__, attr)
3738
3739 # Invalid attributes
3740 self.assertRaises(TypeError, getattr, c, 9)
3741 self.assertRaises(TypeError, setattr, c, 9)
3742
3743 # Invalid values in constructor
3744 self.assertRaises(TypeError, Context, rounding=999999)
3745 self.assertRaises(TypeError, Context, rounding='xyz')
3746 self.assertRaises(ValueError, Context, clamp=2)
3747 self.assertRaises(ValueError, Context, capitals=-1)
3748 self.assertRaises(KeyError, Context, flags=["P"])
3749 self.assertRaises(KeyError, Context, traps=["Q"])
3750
3751 # Type error in conversion
3752 self.assertRaises(TypeError, Context, flags=(0,1))
3753 self.assertRaises(TypeError, Context, traps=(1,0))
3754
3755class CContextInputValidation(ContextInputValidation):
3756 decimal = C
3757class PyContextInputValidation(ContextInputValidation):
3758 decimal = P
3759
3760class ContextSubclassing(unittest.TestCase):
3761
3762 def test_context_subclassing(self):
3763 decimal = self.decimal
3764 Decimal = decimal.Decimal
3765 Context = decimal.Context
3766 ROUND_HALF_EVEN = decimal.ROUND_HALF_EVEN
3767 ROUND_DOWN = decimal.ROUND_DOWN
3768 Clamped = decimal.Clamped
3769 DivisionByZero = decimal.DivisionByZero
3770 Inexact = decimal.Inexact
3771 Overflow = decimal.Overflow
3772 Rounded = decimal.Rounded
3773 Subnormal = decimal.Subnormal
3774 Underflow = decimal.Underflow
3775 InvalidOperation = decimal.InvalidOperation
3776
3777 class MyContext(Context):
3778 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
3779 capitals=None, clamp=None, flags=None,
3780 traps=None):
3781 Context.__init__(self)
3782 if prec is not None:
3783 self.prec = prec
3784 if rounding is not None:
3785 self.rounding = rounding
3786 if Emin is not None:
3787 self.Emin = Emin
3788 if Emax is not None:
3789 self.Emax = Emax
3790 if capitals is not None:
3791 self.capitals = capitals
3792 if clamp is not None:
3793 self.clamp = clamp
3794 if flags is not None:
3795 if isinstance(flags, list):
3796 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
3797 self.flags = flags
3798 if traps is not None:
3799 if isinstance(traps, list):
3800 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
3801 self.traps = traps
3802
3803 c = Context()
3804 d = MyContext()
3805 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
3806 'flags', 'traps'):
3807 self.assertEqual(getattr(c, attr), getattr(d, attr))
3808
3809 # prec
3810 self.assertRaises(ValueError, MyContext, **{'prec':-1})
3811 c = MyContext(prec=1)
3812 self.assertEqual(c.prec, 1)
3813 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
3814
3815 # rounding
3816 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
3817 c = MyContext(rounding=ROUND_DOWN, prec=1)
3818 self.assertEqual(c.rounding, ROUND_DOWN)
3819 self.assertEqual(c.plus(Decimal('9.9')), 9)
3820
3821 # Emin
3822 self.assertRaises(ValueError, MyContext, **{'Emin':5})
3823 c = MyContext(Emin=-1, prec=1)
3824 self.assertEqual(c.Emin, -1)
3825 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
3826 self.assertEqual(x, Decimal('0.0'))
3827 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
3828 self.assertTrue(c.flags[signal])
3829
3830 # Emax
3831 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
3832 c = MyContext(Emax=1, prec=1)
3833 self.assertEqual(c.Emax, 1)
3834 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
3835 if self.decimal == C:
3836 for signal in (Inexact, Overflow, Rounded):
3837 self.assertTrue(c.flags[signal])
3838
3839 # capitals
3840 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
3841 c = MyContext(capitals=0)
3842 self.assertEqual(c.capitals, 0)
3843 x = c.create_decimal('1E222')
3844 self.assertEqual(c.to_sci_string(x), '1e+222')
3845
3846 # clamp
3847 self.assertRaises(ValueError, MyContext, **{'clamp':2})
3848 c = MyContext(clamp=1, Emax=99)
3849 self.assertEqual(c.clamp, 1)
3850 x = c.plus(Decimal('1e99'))
3851 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
3852
3853 # flags
3854 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
3855 c = MyContext(flags=[Rounded, DivisionByZero])
3856 for signal in (Rounded, DivisionByZero):
3857 self.assertTrue(c.flags[signal])
3858 c.clear_flags()
3859 for signal in OrderedSignals[decimal]:
3860 self.assertFalse(c.flags[signal])
3861
3862 # traps
3863 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
3864 c = MyContext(traps=[Rounded, DivisionByZero])
3865 for signal in (Rounded, DivisionByZero):
3866 self.assertTrue(c.traps[signal])
3867 c.clear_traps()
3868 for signal in OrderedSignals[decimal]:
3869 self.assertFalse(c.traps[signal])
3870
3871class CContextSubclassing(ContextSubclassing):
3872 decimal = C
3873class PyContextSubclassing(ContextSubclassing):
3874 decimal = P
3875
3876@skip_if_extra_functionality
3877class CheckAttributes(unittest.TestCase):
3878
3879 def test_module_attributes(self):
3880
3881 # Architecture dependent context limits
3882 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
3883 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
3884 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
3885 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
3886
3887 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
3888 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
3889
3890 self.assertEqual(C.__version__, P.__version__)
3891
3892 x = dir(C)
3893 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02003894 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01003895
3896 def test_context_attributes(self):
3897
3898 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
3899 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
3900 self.assertEqual(set(x) - set(y), set())
3901
3902 def test_decimal_attributes(self):
3903
3904 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3905 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3906 self.assertEqual(set(x) - set(y), set())
3907
3908class Coverage(unittest.TestCase):
3909
3910 def test_adjusted(self):
3911 Decimal = self.decimal.Decimal
3912
3913 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
3914 # XXX raise?
3915 self.assertEqual(Decimal('nan').adjusted(), 0)
3916 self.assertEqual(Decimal('inf').adjusted(), 0)
3917
3918 def test_canonical(self):
3919 Decimal = self.decimal.Decimal
3920 getcontext = self.decimal.getcontext
3921
3922 x = Decimal(9).canonical()
3923 self.assertEqual(x, 9)
3924
3925 c = getcontext()
3926 x = c.canonical(Decimal(9))
3927 self.assertEqual(x, 9)
3928
3929 def test_context_repr(self):
3930 c = self.decimal.DefaultContext.copy()
3931
3932 c.prec = 425000000
3933 c.Emax = 425000000
3934 c.Emin = -425000000
3935 c.rounding = self.decimal.ROUND_HALF_DOWN
3936 c.capitals = 0
3937 c.clamp = 1
3938 for sig in OrderedSignals[self.decimal]:
3939 c.flags[sig] = False
3940 c.traps[sig] = False
3941
3942 s = c.__repr__()
3943 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
3944 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
3945 "flags=[], traps=[])"
3946 self.assertEqual(s, t)
3947
3948 def test_implicit_context(self):
3949 Decimal = self.decimal.Decimal
3950 localcontext = self.decimal.localcontext
3951
3952 with localcontext() as c:
3953 c.prec = 1
3954 c.Emax = 1
3955 c.Emin = -1
3956
3957 # abs
3958 self.assertEqual(abs(Decimal("-10")), 10)
3959 # add
3960 self.assertEqual(Decimal("7") + 1, 8)
3961 # divide
3962 self.assertEqual(Decimal("10") / 5, 2)
3963 # divide_int
3964 self.assertEqual(Decimal("10") // 7, 1)
3965 # fma
3966 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
3967 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
3968 # three arg power
3969 self.assertEqual(pow(Decimal(10), 2, 7), 2)
3970 # exp
3971 self.assertEqual(Decimal("1.01").exp(), 3)
3972 # is_normal
3973 self.assertIs(Decimal("0.01").is_normal(), False)
3974 # is_subnormal
3975 self.assertIs(Decimal("0.01").is_subnormal(), True)
3976 # ln
3977 self.assertEqual(Decimal("20").ln(), 3)
3978 # log10
3979 self.assertEqual(Decimal("20").log10(), 1)
3980 # logb
3981 self.assertEqual(Decimal("580").logb(), 2)
3982 # logical_invert
3983 self.assertEqual(Decimal("10").logical_invert(), 1)
3984 # minus
3985 self.assertEqual(-Decimal("-10"), 10)
3986 # multiply
3987 self.assertEqual(Decimal("2") * 4, 8)
3988 # next_minus
3989 self.assertEqual(Decimal("10").next_minus(), 9)
3990 # next_plus
3991 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
3992 # normalize
3993 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
3994 # number_class
3995 self.assertEqual(Decimal("10").number_class(), '+Normal')
3996 # plus
3997 self.assertEqual(+Decimal("-1"), -1)
3998 # remainder
3999 self.assertEqual(Decimal("10") % 7, 3)
4000 # subtract
4001 self.assertEqual(Decimal("10") - 7, 3)
4002 # to_integral_exact
4003 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4004
4005 # Boolean functions
4006 self.assertTrue(Decimal("1").is_canonical())
4007 self.assertTrue(Decimal("1").is_finite())
4008 self.assertTrue(Decimal("1").is_finite())
4009 self.assertTrue(Decimal("snan").is_snan())
4010 self.assertTrue(Decimal("-1").is_signed())
4011 self.assertTrue(Decimal("0").is_zero())
4012 self.assertTrue(Decimal("0").is_zero())
4013
4014 # Copy
4015 with localcontext() as c:
4016 c.prec = 10000
4017 x = 1228 ** 1523
4018 y = -Decimal(x)
4019
4020 z = y.copy_abs()
4021 self.assertEqual(z, x)
4022
4023 z = y.copy_negate()
4024 self.assertEqual(z, x)
4025
4026 z = y.copy_sign(Decimal(1))
4027 self.assertEqual(z, x)
4028
4029 def test_divmod(self):
4030 Decimal = self.decimal.Decimal
4031 localcontext = self.decimal.localcontext
4032 InvalidOperation = self.decimal.InvalidOperation
4033 DivisionByZero = self.decimal.DivisionByZero
4034
4035 with localcontext() as c:
4036 q, r = divmod(Decimal("10912837129"), 1001)
4037 self.assertEqual(q, Decimal('10901935'))
4038 self.assertEqual(r, Decimal('194'))
4039
4040 q, r = divmod(Decimal("NaN"), 7)
4041 self.assertTrue(q.is_nan() and r.is_nan())
4042
4043 c.traps[InvalidOperation] = False
4044 q, r = divmod(Decimal("NaN"), 7)
4045 self.assertTrue(q.is_nan() and r.is_nan())
4046
4047 c.traps[InvalidOperation] = False
4048 c.clear_flags()
4049 q, r = divmod(Decimal("inf"), Decimal("inf"))
4050 self.assertTrue(q.is_nan() and r.is_nan())
4051 self.assertTrue(c.flags[InvalidOperation])
4052
4053 c.clear_flags()
4054 q, r = divmod(Decimal("inf"), 101)
4055 self.assertTrue(q.is_infinite() and r.is_nan())
4056 self.assertTrue(c.flags[InvalidOperation])
4057
4058 c.clear_flags()
4059 q, r = divmod(Decimal(0), 0)
4060 self.assertTrue(q.is_nan() and r.is_nan())
4061 self.assertTrue(c.flags[InvalidOperation])
4062
4063 c.traps[DivisionByZero] = False
4064 c.clear_flags()
4065 q, r = divmod(Decimal(11), 0)
4066 self.assertTrue(q.is_infinite() and r.is_nan())
4067 self.assertTrue(c.flags[InvalidOperation] and
4068 c.flags[DivisionByZero])
4069
4070 def test_power(self):
4071 Decimal = self.decimal.Decimal
4072 localcontext = self.decimal.localcontext
4073 Overflow = self.decimal.Overflow
4074 Rounded = self.decimal.Rounded
4075
4076 with localcontext() as c:
4077 c.prec = 3
4078 c.clear_flags()
4079 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4080 self.assertTrue(c.flags[Rounded])
4081
4082 c.prec = 1
4083 c.Emax = 1
4084 c.Emin = -1
4085 c.clear_flags()
4086 c.traps[Overflow] = False
4087 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4088 self.assertTrue(c.flags[Overflow])
4089
4090 def test_quantize(self):
4091 Decimal = self.decimal.Decimal
4092 localcontext = self.decimal.localcontext
4093 InvalidOperation = self.decimal.InvalidOperation
4094
4095 with localcontext() as c:
4096 c.prec = 1
4097 c.Emax = 1
4098 c.Emin = -1
4099 c.traps[InvalidOperation] = False
4100 x = Decimal(99).quantize(Decimal("1e1"))
4101 self.assertTrue(x.is_nan())
4102
4103 def test_radix(self):
4104 Decimal = self.decimal.Decimal
4105 getcontext = self.decimal.getcontext
4106
4107 c = getcontext()
4108 self.assertEqual(Decimal("1").radix(), 10)
4109 self.assertEqual(c.radix(), 10)
4110
4111 def test_rop(self):
4112 Decimal = self.decimal.Decimal
4113
4114 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4115 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4116 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4117
4118 def test_round(self):
4119 # Python3 behavior: round() returns Decimal
4120 Decimal = self.decimal.Decimal
4121 getcontext = self.decimal.getcontext
4122
4123 c = getcontext()
4124 c.prec = 28
4125
4126 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4127 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4128 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4129 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4130 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4131
4132 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4133 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4134
4135 def test_create_decimal(self):
4136 c = self.decimal.Context()
4137 self.assertRaises(ValueError, c.create_decimal, ["%"])
4138
4139 def test_int(self):
4140 Decimal = self.decimal.Decimal
4141 localcontext = self.decimal.localcontext
4142
4143 with localcontext() as c:
4144 c.prec = 9999
4145 x = Decimal(1221**1271) / 10**3923
4146 self.assertEqual(int(x), 1)
4147 self.assertEqual(x.to_integral(), 2)
4148
4149 def test_copy(self):
4150 Context = self.decimal.Context
4151
4152 c = Context()
4153 c.prec = 10000
4154 x = -(1172 ** 1712)
4155
4156 y = c.copy_abs(x)
4157 self.assertEqual(y, -x)
4158
4159 y = c.copy_negate(x)
4160 self.assertEqual(y, -x)
4161
4162 y = c.copy_sign(x, 1)
4163 self.assertEqual(y, -x)
4164
4165class CCoverage(Coverage):
4166 decimal = C
4167class PyCoverage(Coverage):
4168 decimal = P
4169
4170class PyFunctionality(unittest.TestCase):
4171 """Extra functionality in decimal.py"""
4172
4173 def test_py_quantize_watchexp(self):
4174 # watchexp functionality
4175 Decimal = P.Decimal
4176 localcontext = P.localcontext
4177
4178 with localcontext() as c:
4179 c.prec = 1
4180 c.Emax = 1
4181 c.Emin = -1
4182 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4183 self.assertEqual(x, Decimal('1.00E+5'))
4184
4185 def test_py_alternate_formatting(self):
4186 # triples giving a format, a Decimal, and the expected result
4187 Decimal = P.Decimal
4188 localcontext = P.localcontext
4189
4190 test_values = [
4191 # Issue 7094: Alternate formatting (specified by #)
4192 ('.0e', '1.0', '1e+0'),
4193 ('#.0e', '1.0', '1.e+0'),
4194 ('.0f', '1.0', '1'),
4195 ('#.0f', '1.0', '1.'),
4196 ('g', '1.1', '1.1'),
4197 ('#g', '1.1', '1.1'),
4198 ('.0g', '1', '1'),
4199 ('#.0g', '1', '1.'),
4200 ('.0%', '1.0', '100%'),
4201 ('#.0%', '1.0', '100.%'),
4202 ]
4203 for fmt, d, result in test_values:
4204 self.assertEqual(format(Decimal(d), fmt), result)
4205
4206class PyWhitebox(unittest.TestCase):
4207 """White box testing for decimal.py"""
4208
4209 def test_py_exact_power(self):
4210 # Rarely exercised lines in _power_exact.
4211 Decimal = P.Decimal
4212 localcontext = P.localcontext
4213
4214 with localcontext() as c:
4215 c.prec = 8
4216 x = Decimal(2**16) ** Decimal("-0.5")
4217 self.assertEqual(x, Decimal('0.00390625'))
4218
4219 x = Decimal(2**16) ** Decimal("-0.6")
4220 self.assertEqual(x, Decimal('0.0012885819'))
4221
4222 x = Decimal("256e7") ** Decimal("-0.5")
4223
4224 x = Decimal(152587890625) ** Decimal('-0.0625')
4225 self.assertEqual(x, Decimal("0.2"))
4226
4227 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4228
4229 x = Decimal(5**2659) ** Decimal('-0.0625')
4230
4231 c.prec = 1
4232 x = Decimal("152587890625") ** Decimal('-0.5')
4233 c.prec = 201
4234 x = Decimal(2**578) ** Decimal("-0.5")
4235
4236 def test_py_immutability_operations(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004237 # Do operations and check that it didn't change change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004238 Decimal = P.Decimal
4239 DefaultContext = P.DefaultContext
4240 setcontext = P.setcontext
4241
4242 c = DefaultContext.copy()
4243 c.traps = dict((s, 0) for s in OrderedSignals[P])
4244 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004245
4246 d1 = Decimal('-25e55')
4247 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004248 d2 = Decimal('33e+33')
4249 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004250
4251 def checkSameDec(operation, useOther=False):
4252 if useOther:
4253 eval("d1." + operation + "(d2)")
4254 self.assertEqual(d1._sign, b1._sign)
4255 self.assertEqual(d1._int, b1._int)
4256 self.assertEqual(d1._exp, b1._exp)
4257 self.assertEqual(d2._sign, b2._sign)
4258 self.assertEqual(d2._int, b2._int)
4259 self.assertEqual(d2._exp, b2._exp)
4260 else:
4261 eval("d1." + operation + "()")
4262 self.assertEqual(d1._sign, b1._sign)
4263 self.assertEqual(d1._int, b1._int)
4264 self.assertEqual(d1._exp, b1._exp)
4265 return
4266
4267 Decimal(d1)
4268 self.assertEqual(d1._sign, b1._sign)
4269 self.assertEqual(d1._int, b1._int)
4270 self.assertEqual(d1._exp, b1._exp)
4271
4272 checkSameDec("__abs__")
4273 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004274 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004275 checkSameDec("__eq__", True)
4276 checkSameDec("__ne__", True)
4277 checkSameDec("__le__", True)
4278 checkSameDec("__lt__", True)
4279 checkSameDec("__ge__", True)
4280 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004281 checkSameDec("__float__")
4282 checkSameDec("__floordiv__", True)
4283 checkSameDec("__hash__")
4284 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004285 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004286 checkSameDec("__mod__", True)
4287 checkSameDec("__mul__", True)
4288 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004289 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004290 checkSameDec("__pos__")
4291 checkSameDec("__pow__", True)
4292 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004293 checkSameDec("__rdivmod__", True)
4294 checkSameDec("__repr__")
4295 checkSameDec("__rfloordiv__", True)
4296 checkSameDec("__rmod__", True)
4297 checkSameDec("__rmul__", True)
4298 checkSameDec("__rpow__", True)
4299 checkSameDec("__rsub__", True)
4300 checkSameDec("__str__")
4301 checkSameDec("__sub__", True)
4302 checkSameDec("__truediv__", True)
4303 checkSameDec("adjusted")
4304 checkSameDec("as_tuple")
4305 checkSameDec("compare", True)
4306 checkSameDec("max", True)
4307 checkSameDec("min", True)
4308 checkSameDec("normalize")
4309 checkSameDec("quantize", True)
4310 checkSameDec("remainder_near", True)
4311 checkSameDec("same_quantum", True)
4312 checkSameDec("sqrt")
4313 checkSameDec("to_eng_string")
4314 checkSameDec("to_integral")
4315
Stefan Krah1919b7e2012-03-21 18:25:23 +01004316 def test_py_decimal_id(self):
4317 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004318
Stefan Krah1919b7e2012-03-21 18:25:23 +01004319 d = Decimal(45)
4320 e = Decimal(d)
4321 self.assertEqual(str(e), '45')
4322 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004323
Stefan Krah1919b7e2012-03-21 18:25:23 +01004324 def test_py_rescale(self):
4325 # Coverage
4326 Decimal = P.Decimal
4327 ROUND_UP = P.ROUND_UP
4328 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004329
Stefan Krah1919b7e2012-03-21 18:25:23 +01004330 with localcontext() as c:
4331 x = Decimal("NaN")._rescale(3, ROUND_UP)
4332 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004333
Stefan Krah1919b7e2012-03-21 18:25:23 +01004334 def test_py__round(self):
4335 # Coverage
4336 Decimal = P.Decimal
4337 ROUND_UP = P.ROUND_UP
Christian Heimes0348fb62008-03-26 12:55:56 +00004338
Stefan Krah1919b7e2012-03-21 18:25:23 +01004339 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004340
Stefan Krah1919b7e2012-03-21 18:25:23 +01004341class CFunctionality(unittest.TestCase):
4342 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004343
Stefan Krah1919b7e2012-03-21 18:25:23 +01004344 @requires_extra_functionality
4345 def test_c_ieee_context(self):
4346 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4347 IEEEContext = C.IEEEContext
4348 DECIMAL32 = C.DECIMAL32
4349 DECIMAL64 = C.DECIMAL64
4350 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004351
Stefan Krah1919b7e2012-03-21 18:25:23 +01004352 def assert_rest(self, context):
4353 self.assertEqual(context.clamp, 1)
4354 assert_signals(self, context, 'traps', [])
4355 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004356
Stefan Krah1919b7e2012-03-21 18:25:23 +01004357 c = IEEEContext(DECIMAL32)
4358 self.assertEqual(c.prec, 7)
4359 self.assertEqual(c.Emax, 96)
4360 self.assertEqual(c.Emin, -95)
4361 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004362
Stefan Krah1919b7e2012-03-21 18:25:23 +01004363 c = IEEEContext(DECIMAL64)
4364 self.assertEqual(c.prec, 16)
4365 self.assertEqual(c.Emax, 384)
4366 self.assertEqual(c.Emin, -383)
4367 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004368
Stefan Krah1919b7e2012-03-21 18:25:23 +01004369 c = IEEEContext(DECIMAL128)
4370 self.assertEqual(c.prec, 34)
4371 self.assertEqual(c.Emax, 6144)
4372 self.assertEqual(c.Emin, -6143)
4373 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004374
Stefan Krah1919b7e2012-03-21 18:25:23 +01004375 # Invalid values
4376 self.assertRaises(OverflowError, IEEEContext, 2**63)
4377 self.assertRaises(ValueError, IEEEContext, -1)
4378 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004379
Stefan Krah1919b7e2012-03-21 18:25:23 +01004380 @requires_extra_functionality
4381 def test_c_context(self):
4382 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004383
Stefan Krah1919b7e2012-03-21 18:25:23 +01004384 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4385 self.assertEqual(c._flags, C.DecClamped)
4386 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004387
Stefan Krah1919b7e2012-03-21 18:25:23 +01004388 @requires_extra_functionality
4389 def test_constants(self):
4390 # Condition flags
4391 cond = (
4392 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4393 C.DecDivisionImpossible, C.DecDivisionUndefined,
4394 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4395 C.DecInvalidOperation, C.DecMallocError,
4396 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4397 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004398 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004399
4400 # IEEEContext
4401 self.assertEqual(C.DECIMAL32, 32)
4402 self.assertEqual(C.DECIMAL64, 64)
4403 self.assertEqual(C.DECIMAL128, 128)
4404 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4405
4406 # Rounding modes
4407 for i, v in enumerate(RoundingModes[C]):
4408 self.assertEqual(v, i)
4409 self.assertEqual(C.ROUND_TRUNC, 8)
4410
4411 # Conditions
4412 for i, v in enumerate(cond):
4413 self.assertEqual(v, 1<<i)
4414
4415 self.assertEqual(C.DecIEEEInvalidOperation,
4416 C.DecConversionSyntax|
4417 C.DecDivisionImpossible|
4418 C.DecDivisionUndefined|
4419 C.DecFpuError|
4420 C.DecInvalidContext|
4421 C.DecInvalidOperation|
4422 C.DecMallocError)
4423
4424 self.assertEqual(C.DecErrors,
4425 C.DecIEEEInvalidOperation|
4426 C.DecDivisionByZero)
4427
4428 self.assertEqual(C.DecTraps,
4429 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4430
4431class CWhitebox(unittest.TestCase):
4432 """Whitebox testing for _decimal"""
4433
4434 def test_bignum(self):
4435 # Not exactly whitebox, but too slow with pydecimal.
4436
4437 Decimal = C.Decimal
4438 localcontext = C.localcontext
4439
4440 b1 = 10**35
4441 b2 = 10**36
4442 with localcontext() as c:
4443 c.prec = 1000000
4444 for i in range(5):
4445 a = random.randrange(b1, b2)
4446 b = random.randrange(1000, 1200)
4447 x = a ** b
4448 y = Decimal(a) ** Decimal(b)
4449 self.assertEqual(x, y)
4450
4451 def test_invalid_construction(self):
4452 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4453
4454 def test_c_input_restriction(self):
4455 # Too large for _decimal to be converted exactly
4456 Decimal = C.Decimal
4457 InvalidOperation = C.InvalidOperation
4458 Context = C.Context
4459 localcontext = C.localcontext
4460
4461 with localcontext(Context()):
4462 self.assertRaises(InvalidOperation, Decimal,
4463 "1e9999999999999999999")
4464
4465 def test_c_context_repr(self):
4466 # This test is _decimal-only because flags are not printed
4467 # in the same order.
4468 DefaultContext = C.DefaultContext
4469 FloatOperation = C.FloatOperation
4470 ROUND_HALF_DOWN = C.ROUND_HALF_DOWN
4471
4472 c = DefaultContext.copy()
4473
4474 c.prec = 425000000
4475 c.Emax = 425000000
4476 c.Emin = -425000000
4477 c.rounding = ROUND_HALF_DOWN
4478 c.capitals = 0
4479 c.clamp = 1
4480 for sig in OrderedSignals[C]:
4481 c.flags[sig] = True
4482 c.traps[sig] = True
4483 c.flags[FloatOperation] = True
4484 c.traps[FloatOperation] = True
4485
4486 s = c.__repr__()
4487 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4488 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4489 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4490 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4491 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4492 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4493 self.assertEqual(s, t)
4494
4495 def test_c_context_errors(self):
4496 Context = C.Context
4497 InvalidOperation = C.InvalidOperation
4498 Overflow = C.Overflow
4499 FloatOperation = C.FloatOperation
4500 localcontext = C.localcontext
4501 getcontext = C.getcontext
4502 setcontext = C.setcontext
4503 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4504
4505 c = Context()
4506
4507 # SignalDict: input validation
4508 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4509 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4510 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4511 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4512 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4513 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4514 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4515 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4516
4517 # Test assignment from a signal dict with the correct length but
4518 # one invalid key.
4519 d = c.flags.copy()
4520 del d[FloatOperation]
4521 d["XYZ"] = 91283719
4522 self.assertRaises(KeyError, setattr, c, 'flags', d)
4523 self.assertRaises(KeyError, setattr, c, 'traps', d)
4524
4525 # Input corner cases
4526 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4527 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4528
4529 # prec, Emax, Emin
4530 for attr in ['prec', 'Emax']:
4531 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4532 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4533
4534 # prec, Emax, Emin in context constructor
4535 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4536 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4537 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4538
4539 # Overflow in conversion
4540 self.assertRaises(OverflowError, Context, prec=int_max+1)
4541 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4542 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
4543 self.assertRaises(OverflowError, Context, rounding=int_max+1)
4544 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4545 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4546
4547 # OverflowError, general ValueError
4548 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4549 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4550 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4551 if sys.platform != 'win32':
4552 self.assertRaises(ValueError, setattr, c, attr, int_max)
4553 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4554
4555 # OverflowError, general TypeError
4556 for attr in ('rounding',):
4557 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4558 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4559 if sys.platform != 'win32':
4560 self.assertRaises(TypeError, setattr, c, attr, int_max)
4561 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4562
4563 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4564 if C.MAX_PREC == 425000000:
4565 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4566 int_max+1)
4567 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4568 int_max+1)
4569 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4570 -int_max-2)
4571
4572 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4573 if C.MAX_PREC == 425000000:
4574 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4575 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4576 1070000001)
4577 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4578 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4579 1070000001)
4580 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4581 -1070000001)
4582 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4583
4584 # capitals, clamp
4585 for attr in ['capitals', 'clamp']:
4586 self.assertRaises(ValueError, setattr, c, attr, -1)
4587 self.assertRaises(ValueError, setattr, c, attr, 2)
4588 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4589 if HAVE_CONFIG_64:
4590 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4591 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4592
4593 # Invalid local context
4594 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4595 locals())
4596
4597 # setcontext
4598 saved_context = getcontext()
4599 self.assertRaises(TypeError, setcontext, "xyz")
4600 setcontext(saved_context)
4601
4602 @requires_extra_functionality
4603 def test_c_context_errors_extra(self):
4604 Context = C.Context
4605 InvalidOperation = C.InvalidOperation
4606 Overflow = C.Overflow
4607 localcontext = C.localcontext
4608 getcontext = C.getcontext
4609 setcontext = C.setcontext
4610 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4611
4612 c = Context()
4613
4614 # Input corner cases
4615 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4616
4617 # OverflowError, general ValueError
4618 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4619 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4620 if sys.platform != 'win32':
4621 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4622 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4623
4624 # OverflowError, general TypeError
4625 for attr in ('_flags', '_traps'):
4626 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4627 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4628 if sys.platform != 'win32':
4629 self.assertRaises(TypeError, setattr, c, attr, int_max)
4630 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4631
4632 # _allcr
4633 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4634 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4635 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4636 if HAVE_CONFIG_64:
4637 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4638 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4639
4640 # _flags, _traps
4641 for attr in ['_flags', '_traps']:
4642 self.assertRaises(TypeError, setattr, c, attr, 999999)
4643 self.assertRaises(TypeError, setattr, c, attr, 'x')
4644
4645 def test_c_valid_context(self):
4646 # These tests are for code coverage in _decimal.
4647 DefaultContext = C.DefaultContext
4648 ROUND_HALF_UP = C.ROUND_HALF_UP
4649 Clamped = C.Clamped
4650 Underflow = C.Underflow
4651 Inexact = C.Inexact
4652 Rounded = C.Rounded
4653 Subnormal = C.Subnormal
4654
4655 c = DefaultContext.copy()
4656
4657 # Exercise all getters and setters
4658 c.prec = 34
4659 c.rounding = ROUND_HALF_UP
4660 c.Emax = 3000
4661 c.Emin = -3000
4662 c.capitals = 1
4663 c.clamp = 0
4664
4665 self.assertEqual(c.prec, 34)
4666 self.assertEqual(c.rounding, ROUND_HALF_UP)
4667 self.assertEqual(c.Emin, -3000)
4668 self.assertEqual(c.Emax, 3000)
4669 self.assertEqual(c.capitals, 1)
4670 self.assertEqual(c.clamp, 0)
4671
4672 self.assertEqual(c.Etiny(), -3033)
4673 self.assertEqual(c.Etop(), 2967)
4674
4675 # Exercise all unsafe setters
4676 if C.MAX_PREC == 425000000:
4677 c._unsafe_setprec(999999999)
4678 c._unsafe_setemax(999999999)
4679 c._unsafe_setemin(-999999999)
4680 self.assertEqual(c.prec, 999999999)
4681 self.assertEqual(c.Emax, 999999999)
4682 self.assertEqual(c.Emin, -999999999)
4683
4684 @requires_extra_functionality
4685 def test_c_valid_context_extra(self):
4686 DefaultContext = C.DefaultContext
4687
4688 c = DefaultContext.copy()
4689 self.assertEqual(c._allcr, 1)
4690 c._allcr = 0
4691 self.assertEqual(c._allcr, 0)
4692
4693 def test_c_round(self):
4694 # Restricted input.
4695 Decimal = C.Decimal
4696 InvalidOperation = C.InvalidOperation
4697 localcontext = C.localcontext
4698 MAX_EMAX = C.MAX_EMAX
4699 MIN_ETINY = C.MIN_ETINY
4700 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4701
4702 with localcontext() as c:
4703 c.traps[InvalidOperation] = True
4704 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4705 -int_max-1)
4706 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4707 int_max)
4708 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4709 int(MAX_EMAX+1))
4710 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4711 -int(MIN_ETINY-1))
4712 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4713 -int_max-2)
4714 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4715 int_max+1)
4716
4717 def test_c_format(self):
4718 # Restricted input
4719 Decimal = C.Decimal
4720 InvalidOperation = C.InvalidOperation
4721 Rounded = C.Rounded
4722 localcontext = C.localcontext
4723 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4724
4725 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4726 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4727 self.assertRaises(TypeError, Decimal(1).__format__, [])
4728
4729 with localcontext() as c:
4730 c.traps[InvalidOperation] = True
4731 c.traps[Rounded] = True
4732 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4733 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4734 self.assertRaises(InvalidOperation, Decimal("1.23456789").__format__,
4735 "=%d.1" % maxsize)
4736
4737 def test_c_integral(self):
4738 Decimal = C.Decimal
4739 Inexact = C.Inexact
4740 ROUND_UP = C.ROUND_UP
4741 localcontext = C.localcontext
4742
4743 x = Decimal(10)
4744 self.assertEqual(x.to_integral(), 10)
4745 self.assertRaises(TypeError, x.to_integral, '10')
4746 self.assertRaises(TypeError, x.to_integral, 10, 'x')
4747 self.assertRaises(TypeError, x.to_integral, 10)
4748
4749 self.assertEqual(x.to_integral_value(), 10)
4750 self.assertRaises(TypeError, x.to_integral_value, '10')
4751 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
4752 self.assertRaises(TypeError, x.to_integral_value, 10)
4753
4754 self.assertEqual(x.to_integral_exact(), 10)
4755 self.assertRaises(TypeError, x.to_integral_exact, '10')
4756 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
4757 self.assertRaises(TypeError, x.to_integral_exact, 10)
4758
4759 with localcontext() as c:
4760 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
4761 self.assertEqual(x, Decimal('100000000000000000000000000'))
4762
4763 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
4764 self.assertEqual(x, Decimal('100000000000000000000000000'))
4765
4766 c.traps[Inexact] = True
4767 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
4768
4769 def test_c_funcs(self):
4770 # Invalid arguments
4771 Decimal = C.Decimal
4772 InvalidOperation = C.InvalidOperation
4773 DivisionByZero = C.DivisionByZero
4774 ROUND_UP = C.ROUND_UP
4775 getcontext = C.getcontext
4776 localcontext = C.localcontext
4777
4778 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
4779
4780 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
4781 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
4782 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
4783
Raymond Hettinger771ed762009-01-03 19:20:32 +00004784 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01004785 TypeError,
4786 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00004787 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004788 self.assertRaises(
4789 TypeError,
4790 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
4791 )
4792 self.assertRaises(
4793 TypeError,
4794 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
4795 )
4796 self.assertRaises(
4797 TypeError,
4798 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
4799 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00004800
Stefan Krah1919b7e2012-03-21 18:25:23 +01004801 with localcontext() as c:
4802 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004803
Stefan Krah1919b7e2012-03-21 18:25:23 +01004804 # Invalid arguments
4805 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
4806 self.assertRaises(TypeError, c.canonical, 200)
4807 self.assertRaises(TypeError, c.is_canonical, 200)
4808 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
4809 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004810
Stefan Krah1919b7e2012-03-21 18:25:23 +01004811 self.assertEqual(str(c.canonical(Decimal(200))), '200')
4812 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00004813
Stefan Krah1919b7e2012-03-21 18:25:23 +01004814 c.traps[DivisionByZero] = True
4815 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
4816 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
4817 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00004818
Stefan Krah1919b7e2012-03-21 18:25:23 +01004819 c.clear_flags()
4820 c.traps[InvalidOperation] = True
4821 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
4822 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
4823 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00004824
Stefan Krah1919b7e2012-03-21 18:25:23 +01004825 c.traps[InvalidOperation] = True
4826 c.prec = 2
4827 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00004828
Stefan Krah1919b7e2012-03-21 18:25:23 +01004829 @requires_extra_functionality
4830 def test_c_context_templates(self):
4831 self.assertEqual(
4832 C.BasicContext._traps,
4833 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
4834 C.DecUnderflow|C.DecClamped
4835 )
4836 self.assertEqual(
4837 C.DefaultContext._traps,
4838 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
4839 )
Mark Dickinson84230a12010-02-18 14:49:50 +00004840
Stefan Krah1919b7e2012-03-21 18:25:23 +01004841 @requires_extra_functionality
4842 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00004843
Stefan Krah1919b7e2012-03-21 18:25:23 +01004844 # SignalDict coverage
4845 Context = C.Context
4846 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00004847
Stefan Krah1919b7e2012-03-21 18:25:23 +01004848 InvalidOperation = C.InvalidOperation
4849 DivisionByZero = C.DivisionByZero
4850 Overflow = C.Overflow
4851 Subnormal = C.Subnormal
4852 Underflow = C.Underflow
4853 Rounded = C.Rounded
4854 Inexact = C.Inexact
4855 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00004856
Stefan Krah1919b7e2012-03-21 18:25:23 +01004857 DecClamped = C.DecClamped
4858 DecInvalidOperation = C.DecInvalidOperation
4859 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00004860
Stefan Krah1919b7e2012-03-21 18:25:23 +01004861 def assertIsExclusivelySet(signal, signal_dict):
4862 for sig in signal_dict:
4863 if sig == signal:
4864 self.assertTrue(signal_dict[sig])
4865 else:
4866 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00004867
Stefan Krah1919b7e2012-03-21 18:25:23 +01004868 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00004869
Stefan Krah1919b7e2012-03-21 18:25:23 +01004870 # Signal dict methods
4871 self.assertTrue(Overflow in c.traps)
4872 c.clear_traps()
4873 for k in c.traps.keys():
4874 c.traps[k] = True
4875 for v in c.traps.values():
4876 self.assertTrue(v)
4877 c.clear_traps()
4878 for k, v in c.traps.items():
4879 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00004880
Stefan Krah1919b7e2012-03-21 18:25:23 +01004881 self.assertFalse(c.flags.get(Overflow))
4882 self.assertIs(c.flags.get("x"), None)
4883 self.assertEqual(c.flags.get("x", "y"), "y")
4884 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00004885
Stefan Krah1919b7e2012-03-21 18:25:23 +01004886 self.assertEqual(len(c.flags), len(c.traps))
4887 s = sys.getsizeof(c.flags)
4888 s = sys.getsizeof(c.traps)
4889 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00004890
Stefan Krah1919b7e2012-03-21 18:25:23 +01004891 # Set flags/traps.
4892 c.clear_flags()
4893 c._flags = DecClamped
4894 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00004895
Stefan Krah1919b7e2012-03-21 18:25:23 +01004896 c.clear_traps()
4897 c._traps = DecInvalidOperation
4898 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00004899
Stefan Krah1919b7e2012-03-21 18:25:23 +01004900 # Set flags/traps from dictionary.
4901 c.clear_flags()
4902 d = c.flags.copy()
4903 d[DivisionByZero] = True
4904 c.flags = d
4905 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004906
Stefan Krah1919b7e2012-03-21 18:25:23 +01004907 c.clear_traps()
4908 d = c.traps.copy()
4909 d[Underflow] = True
4910 c.traps = d
4911 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004912
Stefan Krah1919b7e2012-03-21 18:25:23 +01004913 # Random constructors
4914 IntSignals = {
4915 Clamped: C.DecClamped,
4916 Rounded: C.DecRounded,
4917 Inexact: C.DecInexact,
4918 Subnormal: C.DecSubnormal,
4919 Underflow: C.DecUnderflow,
4920 Overflow: C.DecOverflow,
4921 DivisionByZero: C.DecDivisionByZero,
4922 InvalidOperation: C.DecIEEEInvalidOperation
4923 }
4924 IntCond = [
4925 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
4926 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
4927 C.DecConversionSyntax,
4928 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01004929
Stefan Krah1919b7e2012-03-21 18:25:23 +01004930 lim = len(OrderedSignals[C])
4931 for r in range(lim):
4932 for t in range(lim):
4933 for round in RoundingModes[C]:
4934 flags = random.sample(OrderedSignals[C], r)
4935 traps = random.sample(OrderedSignals[C], t)
4936 prec = random.randrange(1, 10000)
4937 emin = random.randrange(-10000, 0)
4938 emax = random.randrange(0, 10000)
4939 clamp = random.randrange(0, 2)
4940 caps = random.randrange(0, 2)
4941 cr = random.randrange(0, 2)
4942 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
4943 capitals=caps, clamp=clamp, flags=list(flags),
4944 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00004945
Stefan Krah1919b7e2012-03-21 18:25:23 +01004946 self.assertEqual(c.prec, prec)
4947 self.assertEqual(c.rounding, round)
4948 self.assertEqual(c.Emin, emin)
4949 self.assertEqual(c.Emax, emax)
4950 self.assertEqual(c.capitals, caps)
4951 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00004952
Stefan Krah1919b7e2012-03-21 18:25:23 +01004953 f = 0
4954 for x in flags:
4955 f |= IntSignals[x]
4956 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004957
Stefan Krah1919b7e2012-03-21 18:25:23 +01004958 f = 0
4959 for x in traps:
4960 f |= IntSignals[x]
4961 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004962
Stefan Krah1919b7e2012-03-21 18:25:23 +01004963 for cond in IntCond:
4964 c._flags = cond
4965 self.assertTrue(c._flags&DecIEEEInvalidOperation)
4966 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004967
Stefan Krah1919b7e2012-03-21 18:25:23 +01004968 for cond in IntCond:
4969 c._traps = cond
4970 self.assertTrue(c._traps&DecIEEEInvalidOperation)
4971 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004972
Stefan Krah1919b7e2012-03-21 18:25:23 +01004973 def test_invalid_override(self):
4974 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00004975
Stefan Krah1919b7e2012-03-21 18:25:23 +01004976 try:
4977 from locale import CHAR_MAX
4978 except ImportError:
4979 return
Mark Dickinson84230a12010-02-18 14:49:50 +00004980
Stefan Krah1919b7e2012-03-21 18:25:23 +01004981 def make_grouping(lst):
4982 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00004983
Stefan Krah1919b7e2012-03-21 18:25:23 +01004984 def get_fmt(x, override=None, fmt='n'):
4985 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004986
Stefan Krah1919b7e2012-03-21 18:25:23 +01004987 invalid_grouping = {
4988 'decimal_point' : ',',
4989 'grouping' : make_grouping([255, 255, 0]),
4990 'thousands_sep' : ','
4991 }
4992 invalid_dot = {
4993 'decimal_point' : 'xxxxx',
4994 'grouping' : make_grouping([3, 3, 0]),
4995 'thousands_sep' : ','
4996 }
4997 invalid_sep = {
4998 'decimal_point' : '.',
4999 'grouping' : make_grouping([3, 3, 0]),
5000 'thousands_sep' : 'yyyyy'
5001 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005002
Stefan Krah1919b7e2012-03-21 18:25:23 +01005003 if CHAR_MAX == 127: # negative grouping in override
5004 self.assertRaises(ValueError, get_fmt, 12345,
5005 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005006
Stefan Krah1919b7e2012-03-21 18:25:23 +01005007 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5008 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005009
Stefan Krah0774e9b2012-04-05 15:21:58 +02005010 def test_exact_conversion(self):
5011 Decimal = C.Decimal
5012 localcontext = C.localcontext
5013 InvalidOperation = C.InvalidOperation
5014
5015 with localcontext() as c:
5016
5017 c.traps[InvalidOperation] = True
5018
5019 # Clamped
5020 x = "0e%d" % sys.maxsize
5021 self.assertRaises(InvalidOperation, Decimal, x)
5022
5023 x = "0e%d" % (-sys.maxsize-1)
5024 self.assertRaises(InvalidOperation, Decimal, x)
5025
5026 # Overflow
5027 x = "1e%d" % sys.maxsize
5028 self.assertRaises(InvalidOperation, Decimal, x)
5029
5030 # Underflow
5031 x = "1e%d" % (-sys.maxsize-1)
5032 self.assertRaises(InvalidOperation, Decimal, x)
5033
Stefan Krahff3eca02012-04-05 15:46:19 +02005034 def test_from_tuple(self):
5035 Decimal = C.Decimal
5036 localcontext = C.localcontext
5037 InvalidOperation = C.InvalidOperation
5038 Overflow = C.Overflow
5039 Underflow = C.Underflow
5040
5041 with localcontext() as c:
5042
5043 c.traps[InvalidOperation] = True
5044 c.traps[Overflow] = True
5045 c.traps[Underflow] = True
5046
5047 # SSIZE_MAX
5048 x = (1, (), sys.maxsize)
5049 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5050 self.assertRaises(InvalidOperation, Decimal, x)
5051
5052 x = (1, (0, 1, 2), sys.maxsize)
5053 self.assertRaises(Overflow, c.create_decimal, x)
5054 self.assertRaises(InvalidOperation, Decimal, x)
5055
5056 # SSIZE_MIN
5057 x = (1, (), -sys.maxsize-1)
5058 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5059 self.assertRaises(InvalidOperation, Decimal, x)
5060
5061 x = (1, (0, 1, 2), -sys.maxsize-1)
5062 self.assertRaises(Underflow, c.create_decimal, x)
5063 self.assertRaises(InvalidOperation, Decimal, x)
5064
5065 # OverflowError
5066 x = (1, (), sys.maxsize+1)
5067 self.assertRaises(OverflowError, c.create_decimal, x)
5068 self.assertRaises(OverflowError, Decimal, x)
5069
5070 x = (1, (), -sys.maxsize-2)
5071 self.assertRaises(OverflowError, c.create_decimal, x)
5072 self.assertRaises(OverflowError, Decimal, x)
5073
5074 # Specials
5075 x = (1, (), "N")
5076 self.assertEqual(str(Decimal(x)), '-sNaN')
5077 x = (1, (0,), "N")
5078 self.assertEqual(str(Decimal(x)), '-sNaN')
5079 x = (1, (0, 1), "N")
5080 self.assertEqual(str(Decimal(x)), '-sNaN1')
5081
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005082
Stefan Krah1919b7e2012-03-21 18:25:23 +01005083all_tests = [
5084 CExplicitConstructionTest, PyExplicitConstructionTest,
5085 CImplicitConstructionTest, PyImplicitConstructionTest,
5086 CFormatTest, PyFormatTest,
5087 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5088 CThreadingTest, PyThreadingTest,
5089 CUsabilityTest, PyUsabilityTest,
5090 CPythonAPItests, PyPythonAPItests,
5091 CContextAPItests, PyContextAPItests,
5092 CContextWithStatement, PyContextWithStatement,
5093 CContextFlags, PyContextFlags,
5094 CSpecialContexts, PySpecialContexts,
5095 CContextInputValidation, PyContextInputValidation,
5096 CContextSubclassing, PyContextSubclassing,
5097 CCoverage, PyCoverage,
5098 CFunctionality, PyFunctionality,
5099 CWhitebox, PyWhitebox,
5100 CIBMTestCases, PyIBMTestCases,
5101]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005102
Stefan Krah1919b7e2012-03-21 18:25:23 +01005103# Delete C tests if _decimal.so is not present.
5104if not C:
5105 all_tests = all_tests[1::2]
5106else:
5107 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005108
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005109
5110def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005111 """ Execute the tests.
5112
Raymond Hettingered20ad82004-09-04 20:09:13 +00005113 Runs all arithmetic tests if arith is True or if the "decimal" resource
5114 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005115 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005116
Stefan Krah1919b7e2012-03-21 18:25:23 +01005117 init(C)
5118 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005119 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00005120 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005121 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005122
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005123 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005124 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005125 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005126 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005127
5128 # Dynamically build custom test definition for each file in the test
5129 # directory and add the definitions to the DecimalTest class. This
5130 # procedure insures that new files do not get skipped.
5131 for filename in os.listdir(directory):
5132 if '.decTest' not in filename or filename.startswith("."):
5133 continue
5134 head, tail = filename.split('.')
5135 if todo_tests is not None and head not in todo_tests:
5136 continue
5137 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005138 setattr(CIBMTestCases, 'test_' + head, tester)
5139 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005140 del filename, head, tail, tester
5141
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005142
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005143 try:
5144 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005145 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005146 from doctest import IGNORE_EXCEPTION_DETAIL
5147 savedecimal = sys.modules['decimal']
5148 if C:
5149 sys.modules['decimal'] = C
5150 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5151 sys.modules['decimal'] = P
5152 run_doctest(P, verbose)
5153 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005154 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005155 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5156 P.setcontext(ORIGINAL_CONTEXT[P])
5157 if not C:
5158 warnings.warn('C tests skipped: no module named _decimal.',
5159 UserWarning)
5160 if not orig_sys_decimal is sys.modules['decimal']:
5161 raise TestFailed("Internal error: unbalanced number of changes to "
5162 "sys.modules['decimal'].")
5163
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005164
5165if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005166 import optparse
5167 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5168 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5169 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5170 (opt, args) = p.parse_args()
5171
5172 if opt.skip:
5173 test_main(arith=False, verbose=True)
5174 elif args:
5175 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005176 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005177 test_main(arith=True, verbose=True)