blob: e13870965a9dadcc68cc172f5348e1d68ffba117 [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
Stefan Krah040e3112012-12-15 22:33:33 +01002092 def test_none_args(self):
2093 Decimal = self.decimal.Decimal
2094 Context = self.decimal.Context
2095 localcontext = self.decimal.localcontext
2096 InvalidOperation = self.decimal.InvalidOperation
2097 DivisionByZero = self.decimal.DivisionByZero
2098 Overflow = self.decimal.Overflow
2099 Underflow = self.decimal.Underflow
2100 Subnormal = self.decimal.Subnormal
2101 Inexact = self.decimal.Inexact
2102 Rounded = self.decimal.Rounded
2103 Clamped = self.decimal.Clamped
2104 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
2105 ROUND_DOWN = self.decimal.ROUND_DOWN
2106 ROUND_UP = self.decimal.ROUND_UP
2107
2108 with localcontext(Context()) as c:
2109 c.prec = 7
2110 c.Emax = 999
2111 c.Emin = -999
2112
2113 x = Decimal("111")
2114 y = Decimal("1e9999")
2115 z = Decimal("1e-9999")
2116
2117 ##### Unary functions
2118 c.clear_flags()
2119 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2120 self.assertTrue(c.flags[Inexact])
2121 self.assertTrue(c.flags[Rounded])
2122 c.clear_flags()
2123 self.assertRaises(Overflow, y.exp, context=None)
2124 self.assertTrue(c.flags[Overflow])
2125
2126 self.assertIs(z.is_normal(context=None), False)
2127 self.assertIs(z.is_subnormal(context=None), True)
2128
2129 c.clear_flags()
2130 self.assertEqual(str(x.ln(context=None)), '4.709530')
2131 self.assertTrue(c.flags[Inexact])
2132 self.assertTrue(c.flags[Rounded])
2133 c.clear_flags()
2134 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2135 self.assertTrue(c.flags[InvalidOperation])
2136
2137 c.clear_flags()
2138 self.assertEqual(str(x.log10(context=None)), '2.045323')
2139 self.assertTrue(c.flags[Inexact])
2140 self.assertTrue(c.flags[Rounded])
2141 c.clear_flags()
2142 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2143 self.assertTrue(c.flags[InvalidOperation])
2144
2145 c.clear_flags()
2146 self.assertEqual(str(x.logb(context=None)), '2')
2147 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2148 self.assertTrue(c.flags[DivisionByZero])
2149
2150 c.clear_flags()
2151 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2152 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2153 self.assertTrue(c.flags[InvalidOperation])
2154
2155 c.clear_flags()
2156 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2157 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2158 self.assertTrue(c.flags[InvalidOperation])
2159
2160 c.clear_flags()
2161 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2162 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2163 self.assertTrue(c.flags[InvalidOperation])
2164
2165 c.clear_flags()
2166 self.assertEqual(str(z.normalize(context=None)), '0')
2167 self.assertRaises(Overflow, y.normalize, context=None)
2168 self.assertTrue(c.flags[Overflow])
2169
2170 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2171
2172 c.clear_flags()
2173 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2174 self.assertTrue(c.flags[Clamped])
2175 self.assertTrue(c.flags[Inexact])
2176 self.assertTrue(c.flags[Rounded])
2177 self.assertTrue(c.flags[Subnormal])
2178 self.assertTrue(c.flags[Underflow])
2179 c.clear_flags()
2180 self.assertRaises(Overflow, y.sqrt, context=None)
2181 self.assertTrue(c.flags[Overflow])
2182
2183 c.capitals = 0
2184 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2185 c.capitals = 1
2186
2187
2188 ##### Binary functions
2189 c.clear_flags()
2190 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2191 self.assertEqual(ans, 'NaN1287828')
2192 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2193 self.assertTrue(c.flags[InvalidOperation])
2194
2195 c.clear_flags()
2196 ans = str(x.compare_signal(8224, context=None))
2197 self.assertEqual(ans, '-1')
2198 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2199 self.assertTrue(c.flags[InvalidOperation])
2200
2201 c.clear_flags()
2202 ans = str(x.logical_and(101, context=None))
2203 self.assertEqual(ans, '101')
2204 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2205 self.assertTrue(c.flags[InvalidOperation])
2206
2207 c.clear_flags()
2208 ans = str(x.logical_or(101, context=None))
2209 self.assertEqual(ans, '111')
2210 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2211 self.assertTrue(c.flags[InvalidOperation])
2212
2213 c.clear_flags()
2214 ans = str(x.logical_xor(101, context=None))
2215 self.assertEqual(ans, '10')
2216 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2217 self.assertTrue(c.flags[InvalidOperation])
2218
2219 c.clear_flags()
2220 ans = str(x.max(101, context=None))
2221 self.assertEqual(ans, '111')
2222 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2223 self.assertTrue(c.flags[InvalidOperation])
2224
2225 c.clear_flags()
2226 ans = str(x.max_mag(101, context=None))
2227 self.assertEqual(ans, '111')
2228 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2229 self.assertTrue(c.flags[InvalidOperation])
2230
2231 c.clear_flags()
2232 ans = str(x.min(101, context=None))
2233 self.assertEqual(ans, '101')
2234 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2235 self.assertTrue(c.flags[InvalidOperation])
2236
2237 c.clear_flags()
2238 ans = str(x.min_mag(101, context=None))
2239 self.assertEqual(ans, '101')
2240 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2241 self.assertTrue(c.flags[InvalidOperation])
2242
2243 c.clear_flags()
2244 ans = str(x.remainder_near(101, context=None))
2245 self.assertEqual(ans, '10')
2246 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2247 self.assertTrue(c.flags[InvalidOperation])
2248
2249 c.clear_flags()
2250 ans = str(x.rotate(2, context=None))
2251 self.assertEqual(ans, '11100')
2252 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2253 self.assertTrue(c.flags[InvalidOperation])
2254
2255 c.clear_flags()
2256 ans = str(x.scaleb(7, context=None))
2257 self.assertEqual(ans, '1.11E+9')
2258 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2259 self.assertTrue(c.flags[InvalidOperation])
2260
2261 c.clear_flags()
2262 ans = str(x.shift(2, context=None))
2263 self.assertEqual(ans, '11100')
2264 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2265 self.assertTrue(c.flags[InvalidOperation])
2266
2267
2268 ##### Ternary functions
2269 c.clear_flags()
2270 ans = str(x.fma(2, 3, context=None))
2271 self.assertEqual(ans, '225')
2272 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2273 self.assertTrue(c.flags[Overflow])
2274
2275
2276 ##### Special cases
2277 c.rounding = ROUND_HALF_EVEN
2278 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2279 self.assertEqual(ans, '2')
2280 c.rounding = ROUND_DOWN
2281 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2282 self.assertEqual(ans, '1')
2283 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2284 self.assertEqual(ans, '2')
2285 c.clear_flags()
2286 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2287 self.assertTrue(c.flags[InvalidOperation])
2288
2289 c.rounding = ROUND_HALF_EVEN
2290 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2291 self.assertEqual(ans, '2')
2292 c.rounding = ROUND_DOWN
2293 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2294 self.assertEqual(ans, '1')
2295 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2296 self.assertEqual(ans, '2')
2297 c.clear_flags()
2298 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2299 self.assertTrue(c.flags[InvalidOperation])
2300
2301 c.rounding = ROUND_HALF_EVEN
2302 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2303 self.assertEqual(ans, '2')
2304 c.rounding = ROUND_DOWN
2305 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2306 self.assertEqual(ans, '1')
2307 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2308 self.assertEqual(ans, '2')
2309 c.clear_flags()
2310 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2311 self.assertTrue(c.flags[InvalidOperation])
2312
2313 c.rounding = ROUND_UP
2314 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2315 self.assertEqual(ans, '1.501')
2316 c.rounding = ROUND_DOWN
2317 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2318 self.assertEqual(ans, '1.500')
2319 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2320 self.assertEqual(ans, '1.501')
2321 c.clear_flags()
2322 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2323 self.assertTrue(c.flags[InvalidOperation])
2324
2325 with localcontext(Context()) as context:
2326 context.prec = 7
2327 context.Emax = 999
2328 context.Emin = -999
2329 with localcontext(ctx=None) as c:
2330 self.assertEqual(c.prec, 7)
2331 self.assertEqual(c.Emax, 999)
2332 self.assertEqual(c.Emin, -999)
2333
Stefan Krah1919b7e2012-03-21 18:25:23 +01002334 def test_conversions_from_int(self):
2335 # Check that methods taking a second Decimal argument will
2336 # always accept an integer in place of a Decimal.
2337 Decimal = self.decimal.Decimal
2338
2339 self.assertEqual(Decimal(4).compare(3),
2340 Decimal(4).compare(Decimal(3)))
2341 self.assertEqual(Decimal(4).compare_signal(3),
2342 Decimal(4).compare_signal(Decimal(3)))
2343 self.assertEqual(Decimal(4).compare_total(3),
2344 Decimal(4).compare_total(Decimal(3)))
2345 self.assertEqual(Decimal(4).compare_total_mag(3),
2346 Decimal(4).compare_total_mag(Decimal(3)))
2347 self.assertEqual(Decimal(10101).logical_and(1001),
2348 Decimal(10101).logical_and(Decimal(1001)))
2349 self.assertEqual(Decimal(10101).logical_or(1001),
2350 Decimal(10101).logical_or(Decimal(1001)))
2351 self.assertEqual(Decimal(10101).logical_xor(1001),
2352 Decimal(10101).logical_xor(Decimal(1001)))
2353 self.assertEqual(Decimal(567).max(123),
2354 Decimal(567).max(Decimal(123)))
2355 self.assertEqual(Decimal(567).max_mag(123),
2356 Decimal(567).max_mag(Decimal(123)))
2357 self.assertEqual(Decimal(567).min(123),
2358 Decimal(567).min(Decimal(123)))
2359 self.assertEqual(Decimal(567).min_mag(123),
2360 Decimal(567).min_mag(Decimal(123)))
2361 self.assertEqual(Decimal(567).next_toward(123),
2362 Decimal(567).next_toward(Decimal(123)))
2363 self.assertEqual(Decimal(1234).quantize(100),
2364 Decimal(1234).quantize(Decimal(100)))
2365 self.assertEqual(Decimal(768).remainder_near(1234),
2366 Decimal(768).remainder_near(Decimal(1234)))
2367 self.assertEqual(Decimal(123).rotate(1),
2368 Decimal(123).rotate(Decimal(1)))
2369 self.assertEqual(Decimal(1234).same_quantum(1000),
2370 Decimal(1234).same_quantum(Decimal(1000)))
2371 self.assertEqual(Decimal('9.123').scaleb(-100),
2372 Decimal('9.123').scaleb(Decimal(-100)))
2373 self.assertEqual(Decimal(456).shift(-1),
2374 Decimal(456).shift(Decimal(-1)))
2375
2376 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2377 Decimal(-12).fma(Decimal(45), Decimal(67)))
2378 self.assertEqual(Decimal(-12).fma(45, 67),
2379 Decimal(-12).fma(Decimal(45), Decimal(67)))
2380 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2381 Decimal(-12).fma(Decimal(45), Decimal(67)))
2382
2383class CUsabilityTest(UsabilityTest):
2384 decimal = C
2385class PyUsabilityTest(UsabilityTest):
2386 decimal = P
2387
2388class PythonAPItests(unittest.TestCase):
2389
2390 def test_abc(self):
2391 Decimal = self.decimal.Decimal
2392
2393 self.assertTrue(issubclass(Decimal, numbers.Number))
2394 self.assertFalse(issubclass(Decimal, numbers.Real))
2395 self.assertIsInstance(Decimal(0), numbers.Number)
2396 self.assertNotIsInstance(Decimal(0), numbers.Real)
2397
2398 def test_pickle(self):
2399 Decimal = self.decimal.Decimal
2400
2401 savedecimal = sys.modules['decimal']
2402
2403 # Round trip
2404 sys.modules['decimal'] = self.decimal
2405 d = Decimal('-3.141590000')
2406 p = pickle.dumps(d)
2407 e = pickle.loads(p)
2408 self.assertEqual(d, e)
2409
2410 if C:
2411 # Test interchangeability
2412 x = C.Decimal('-3.123e81723')
2413 y = P.Decimal('-3.123e81723')
2414
2415 sys.modules['decimal'] = C
2416 sx = pickle.dumps(x)
2417 sys.modules['decimal'] = P
2418 r = pickle.loads(sx)
2419 self.assertIsInstance(r, P.Decimal)
2420 self.assertEqual(r, y)
2421
2422 sys.modules['decimal'] = P
2423 sy = pickle.dumps(y)
2424 sys.modules['decimal'] = C
2425 r = pickle.loads(sy)
2426 self.assertIsInstance(r, C.Decimal)
2427 self.assertEqual(r, x)
2428
2429 sys.modules['decimal'] = savedecimal
2430
2431 def test_int(self):
2432 Decimal = self.decimal.Decimal
2433 ROUND_DOWN = self.decimal.ROUND_DOWN
2434
2435 for x in range(-250, 250):
2436 s = '%0.2f' % (x / 100.0)
2437 # should work the same as for floats
2438 self.assertEqual(int(Decimal(s)), int(float(s)))
2439 # should work the same as to_integral in the ROUND_DOWN mode
2440 d = Decimal(s)
2441 r = d.to_integral(ROUND_DOWN)
2442 self.assertEqual(Decimal(int(d)), r)
2443
2444 self.assertRaises(ValueError, int, Decimal('-nan'))
2445 self.assertRaises(ValueError, int, Decimal('snan'))
2446 self.assertRaises(OverflowError, int, Decimal('inf'))
2447 self.assertRaises(OverflowError, int, Decimal('-inf'))
2448
2449 def test_trunc(self):
2450 Decimal = self.decimal.Decimal
2451 ROUND_DOWN = self.decimal.ROUND_DOWN
2452
2453 for x in range(-250, 250):
2454 s = '%0.2f' % (x / 100.0)
2455 # should work the same as for floats
2456 self.assertEqual(int(Decimal(s)), int(float(s)))
2457 # should work the same as to_integral in the ROUND_DOWN mode
2458 d = Decimal(s)
2459 r = d.to_integral(ROUND_DOWN)
2460 self.assertEqual(Decimal(math.trunc(d)), r)
2461
2462 def test_from_float(self):
2463
2464 Decimal = self.decimal.Decimal
2465
2466 class MyDecimal(Decimal):
2467 pass
2468
2469 self.assertTrue(issubclass(MyDecimal, Decimal))
2470
2471 r = MyDecimal.from_float(0.1)
2472 self.assertEqual(type(r), MyDecimal)
2473 self.assertEqual(str(r),
2474 '0.1000000000000000055511151231257827021181583404541015625')
2475 bigint = 12345678901234567890123456789
2476 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2477 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2478 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2479 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2480 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2481 str(Decimal('NaN')))
2482 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2483 str(Decimal('Infinity')))
2484 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2485 str(Decimal('-Infinity')))
2486 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2487 for i in range(200):
2488 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2489 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2490
2491 def test_create_decimal_from_float(self):
2492 Decimal = self.decimal.Decimal
2493 Context = self.decimal.Context
2494 ROUND_DOWN = self.decimal.ROUND_DOWN
2495 ROUND_UP = self.decimal.ROUND_UP
2496 Inexact = self.decimal.Inexact
2497
2498 context = Context(prec=5, rounding=ROUND_DOWN)
2499 self.assertEqual(
2500 context.create_decimal_from_float(math.pi),
2501 Decimal('3.1415')
2502 )
2503 context = Context(prec=5, rounding=ROUND_UP)
2504 self.assertEqual(
2505 context.create_decimal_from_float(math.pi),
2506 Decimal('3.1416')
2507 )
2508 context = Context(prec=5, traps=[Inexact])
2509 self.assertRaises(
2510 Inexact,
2511 context.create_decimal_from_float,
2512 math.pi
2513 )
2514 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2515 "Decimal('-0')")
2516 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2517 "Decimal('1')")
2518 self.assertEqual(repr(context.create_decimal_from_float(10)),
2519 "Decimal('10')")
2520
2521 def test_quantize(self):
2522 Decimal = self.decimal.Decimal
2523 Context = self.decimal.Context
2524 InvalidOperation = self.decimal.InvalidOperation
2525 ROUND_DOWN = self.decimal.ROUND_DOWN
2526
2527 c = Context(Emax=99999, Emin=-99999)
2528 self.assertEqual(
2529 Decimal('7.335').quantize(Decimal('.01')),
2530 Decimal('7.34')
2531 )
2532 self.assertEqual(
2533 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2534 Decimal('7.33')
2535 )
2536 self.assertRaises(
2537 InvalidOperation,
2538 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2539 )
2540
2541 c = Context()
2542 d = Decimal("0.871831e800")
2543 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2544 self.assertEqual(x, Decimal('8.71E+799'))
2545
2546 def test_complex(self):
2547 Decimal = self.decimal.Decimal
2548
2549 x = Decimal("9.8182731e181273")
2550 self.assertEqual(x.real, x)
2551 self.assertEqual(x.imag, 0)
2552 self.assertEqual(x.conjugate(), x)
2553
2554 x = Decimal("1")
2555 self.assertEqual(complex(x), complex(float(1)))
2556
2557 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2558 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2559 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2560 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2561
2562 def test_named_parameters(self):
2563 D = self.decimal.Decimal
2564 Context = self.decimal.Context
2565 localcontext = self.decimal.localcontext
2566 InvalidOperation = self.decimal.InvalidOperation
2567 Overflow = self.decimal.Overflow
2568
2569 xc = Context()
2570 xc.prec = 1
2571 xc.Emax = 1
2572 xc.Emin = -1
2573
2574 with localcontext() as c:
2575 c.clear_flags()
2576
2577 self.assertEqual(D(9, xc), 9)
2578 self.assertEqual(D(9, context=xc), 9)
2579 self.assertEqual(D(context=xc, value=9), 9)
2580 self.assertEqual(D(context=xc), 0)
2581 xc.clear_flags()
2582 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2583 self.assertTrue(xc.flags[InvalidOperation])
2584 self.assertFalse(c.flags[InvalidOperation])
2585
2586 xc.clear_flags()
2587 self.assertEqual(D(2).exp(context=xc), 7)
2588 self.assertRaises(Overflow, D(8).exp, context=xc)
2589 self.assertTrue(xc.flags[Overflow])
2590 self.assertFalse(c.flags[Overflow])
2591
2592 xc.clear_flags()
2593 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2594 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2595 self.assertTrue(xc.flags[InvalidOperation])
2596 self.assertFalse(c.flags[InvalidOperation])
2597
2598 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2599 self.assertEqual(D(-1).next_minus(context=xc), -2)
2600 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2601 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2602 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2603 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2604 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2605 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2606
2607 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2608 xc.clear_flags()
2609 self.assertRaises(InvalidOperation,
2610 D("0").compare_signal, D('nan'), context=xc)
2611 self.assertTrue(xc.flags[InvalidOperation])
2612 self.assertFalse(c.flags[InvalidOperation])
2613 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2614 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2615 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2616 D('-0.3'))
2617 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2618 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2619 D('0.0'))
2620 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2621 xc.clear_flags()
2622 self.assertRaises(InvalidOperation,
2623 D("0.2").quantize, D('1e10'), context=xc)
2624 self.assertTrue(xc.flags[InvalidOperation])
2625 self.assertFalse(c.flags[InvalidOperation])
2626 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2627 D('-0.5'))
2628
2629 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2630 D('7E+1'))
2631
2632 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2633 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2634 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2635 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2636 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2637 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2638 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2639 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2640
2641 self.assertFalse(D("0.01").is_normal(context=xc))
2642 self.assertTrue(D("0.01").is_subnormal(context=xc))
2643
2644 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2645 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2646 self.assertRaises(TypeError, D(1).radix, context=xc)
2647
2648 self.assertEqual(D(-111).logb(context=xc), 2)
2649 self.assertEqual(D(0).logical_invert(context=xc), 1)
2650 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2651 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2652
2653 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2654 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2655 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2656 self.assertEqual(D('23').rotate(1, context=xc), 3)
2657 self.assertEqual(D('23').rotate(1, context=xc), 3)
2658 xc.clear_flags()
2659 self.assertRaises(Overflow,
2660 D('23').scaleb, 1, context=xc)
2661 self.assertTrue(xc.flags[Overflow])
2662 self.assertFalse(c.flags[Overflow])
2663 self.assertEqual(D('23').shift(-1, context=xc), 0)
2664
2665 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2666 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2667
Stefan Krah040e3112012-12-15 22:33:33 +01002668 self.assertEqual(D(1).canonical(), 1)
2669 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2670 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2671 self.assertRaises(TypeError, D(1).canonical, context="x")
2672 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002673
Stefan Krahb6405ef2012-03-23 14:46:48 +01002674 def test_exception_hierarchy(self):
2675
2676 decimal = self.decimal
2677 DecimalException = decimal.DecimalException
2678 InvalidOperation = decimal.InvalidOperation
2679 FloatOperation = decimal.FloatOperation
2680 DivisionByZero = decimal.DivisionByZero
2681 Overflow = decimal.Overflow
2682 Underflow = decimal.Underflow
2683 Subnormal = decimal.Subnormal
2684 Inexact = decimal.Inexact
2685 Rounded = decimal.Rounded
2686 Clamped = decimal.Clamped
2687
2688 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2689
2690 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2691 self.assertTrue(issubclass(FloatOperation, DecimalException))
2692 self.assertTrue(issubclass(FloatOperation, TypeError))
2693 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2694 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2695 self.assertTrue(issubclass(Overflow, Rounded))
2696 self.assertTrue(issubclass(Overflow, Inexact))
2697 self.assertTrue(issubclass(Overflow, DecimalException))
2698 self.assertTrue(issubclass(Underflow, Inexact))
2699 self.assertTrue(issubclass(Underflow, Rounded))
2700 self.assertTrue(issubclass(Underflow, Subnormal))
2701 self.assertTrue(issubclass(Underflow, DecimalException))
2702
2703 self.assertTrue(issubclass(Subnormal, DecimalException))
2704 self.assertTrue(issubclass(Inexact, DecimalException))
2705 self.assertTrue(issubclass(Rounded, DecimalException))
2706 self.assertTrue(issubclass(Clamped, DecimalException))
2707
2708 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2709 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2710 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2711 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2712 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2713
Stefan Krah1919b7e2012-03-21 18:25:23 +01002714class CPythonAPItests(PythonAPItests):
2715 decimal = C
2716class PyPythonAPItests(PythonAPItests):
2717 decimal = P
2718
2719class ContextAPItests(unittest.TestCase):
2720
Stefan Krah9a4ff432012-12-16 21:10:35 +01002721 def test_none_args(self):
2722 Context = self.decimal.Context
2723 InvalidOperation = self.decimal.InvalidOperation
2724 DivisionByZero = self.decimal.DivisionByZero
2725 Overflow = self.decimal.Overflow
2726 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
2727
2728 c1 = Context()
2729 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2730 capitals=None, clamp=None, flags=None, traps=None)
2731 for c in [c1, c2]:
2732 self.assertEqual(c.prec, 28)
2733 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2734 self.assertEqual(c.Emax, 999999)
2735 self.assertEqual(c.Emin, -999999)
2736 self.assertEqual(c.capitals, 1)
2737 self.assertEqual(c.clamp, 0)
2738 assert_signals(self, c, 'flags', [])
2739 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2740 Overflow])
2741
Stefan Krah1919b7e2012-03-21 18:25:23 +01002742 def test_pickle(self):
2743
2744 Context = self.decimal.Context
2745
2746 savedecimal = sys.modules['decimal']
2747
2748 # Round trip
2749 sys.modules['decimal'] = self.decimal
2750 c = Context()
2751 e = pickle.loads(pickle.dumps(c))
2752
2753 self.assertEqual(c.prec, e.prec)
2754 self.assertEqual(c.Emin, e.Emin)
2755 self.assertEqual(c.Emax, e.Emax)
2756 self.assertEqual(c.rounding, e.rounding)
2757 self.assertEqual(c.capitals, e.capitals)
2758 self.assertEqual(c.clamp, e.clamp)
2759 self.assertEqual(c.flags, e.flags)
2760 self.assertEqual(c.traps, e.traps)
2761
2762 # Test interchangeability
2763 combinations = [(C, P), (P, C)] if C else [(P, P)]
2764 for dumper, loader in combinations:
2765 for ri, _ in enumerate(RoundingModes[dumper]):
2766 for fi, _ in enumerate(OrderedSignals[dumper]):
2767 for ti, _ in enumerate(OrderedSignals[dumper]):
2768
2769 prec = random.randrange(1, 100)
2770 emin = random.randrange(-100, 0)
2771 emax = random.randrange(1, 100)
2772 caps = random.randrange(2)
2773 clamp = random.randrange(2)
2774
2775 # One module dumps
2776 sys.modules['decimal'] = dumper
2777 c = dumper.Context(
2778 prec=prec, Emin=emin, Emax=emax,
2779 rounding=RoundingModes[dumper][ri],
2780 capitals=caps, clamp=clamp,
2781 flags=OrderedSignals[dumper][:fi],
2782 traps=OrderedSignals[dumper][:ti]
2783 )
2784 s = pickle.dumps(c)
2785
2786 # The other module loads
2787 sys.modules['decimal'] = loader
2788 d = pickle.loads(s)
2789 self.assertIsInstance(d, loader.Context)
2790
2791 self.assertEqual(d.prec, prec)
2792 self.assertEqual(d.Emin, emin)
2793 self.assertEqual(d.Emax, emax)
2794 self.assertEqual(d.rounding, RoundingModes[loader][ri])
2795 self.assertEqual(d.capitals, caps)
2796 self.assertEqual(d.clamp, clamp)
2797 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2798 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2799
2800 sys.modules['decimal'] = savedecimal
2801
2802 def test_equality_with_other_types(self):
2803 Decimal = self.decimal.Decimal
2804
2805 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2806 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2807
2808 def test_copy(self):
2809 # All copies should be deep
2810 Decimal = self.decimal.Decimal
2811 Context = self.decimal.Context
2812
2813 c = Context()
2814 d = c.copy()
2815 self.assertNotEqual(id(c), id(d))
2816 self.assertNotEqual(id(c.flags), id(d.flags))
2817 self.assertNotEqual(id(c.traps), id(d.traps))
2818 k1 = set(c.flags.keys())
2819 k2 = set(d.flags.keys())
2820 self.assertEqual(k1, k2)
2821 self.assertEqual(c.flags, d.flags)
2822
2823 def test__clamp(self):
2824 # In Python 3.2, the private attribute `_clamp` was made
2825 # public (issue 8540), with the old `_clamp` becoming a
2826 # property wrapping `clamp`. For the duration of Python 3.2
2827 # only, the attribute should be gettable/settable via both
2828 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2829 # removed.
2830 Context = self.decimal.Context
2831 c = Context()
2832 self.assertRaises(AttributeError, getattr, c, '_clamp')
2833
2834 def test_abs(self):
2835 Decimal = self.decimal.Decimal
2836 Context = self.decimal.Context
2837
2838 c = Context()
2839 d = c.abs(Decimal(-1))
2840 self.assertEqual(c.abs(-1), d)
2841 self.assertRaises(TypeError, c.abs, '-1')
2842
2843 def test_add(self):
2844 Decimal = self.decimal.Decimal
2845 Context = self.decimal.Context
2846
2847 c = Context()
2848 d = c.add(Decimal(1), Decimal(1))
2849 self.assertEqual(c.add(1, 1), d)
2850 self.assertEqual(c.add(Decimal(1), 1), d)
2851 self.assertEqual(c.add(1, Decimal(1)), d)
2852 self.assertRaises(TypeError, c.add, '1', 1)
2853 self.assertRaises(TypeError, c.add, 1, '1')
2854
2855 def test_compare(self):
2856 Decimal = self.decimal.Decimal
2857 Context = self.decimal.Context
2858
2859 c = Context()
2860 d = c.compare(Decimal(1), Decimal(1))
2861 self.assertEqual(c.compare(1, 1), d)
2862 self.assertEqual(c.compare(Decimal(1), 1), d)
2863 self.assertEqual(c.compare(1, Decimal(1)), d)
2864 self.assertRaises(TypeError, c.compare, '1', 1)
2865 self.assertRaises(TypeError, c.compare, 1, '1')
2866
2867 def test_compare_signal(self):
2868 Decimal = self.decimal.Decimal
2869 Context = self.decimal.Context
2870
2871 c = Context()
2872 d = c.compare_signal(Decimal(1), Decimal(1))
2873 self.assertEqual(c.compare_signal(1, 1), d)
2874 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2875 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2876 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2877 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2878
2879 def test_compare_total(self):
2880 Decimal = self.decimal.Decimal
2881 Context = self.decimal.Context
2882
2883 c = Context()
2884 d = c.compare_total(Decimal(1), Decimal(1))
2885 self.assertEqual(c.compare_total(1, 1), d)
2886 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2887 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2888 self.assertRaises(TypeError, c.compare_total, '1', 1)
2889 self.assertRaises(TypeError, c.compare_total, 1, '1')
2890
2891 def test_compare_total_mag(self):
2892 Decimal = self.decimal.Decimal
2893 Context = self.decimal.Context
2894
2895 c = Context()
2896 d = c.compare_total_mag(Decimal(1), Decimal(1))
2897 self.assertEqual(c.compare_total_mag(1, 1), d)
2898 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2899 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2900 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2901 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2902
2903 def test_copy_abs(self):
2904 Decimal = self.decimal.Decimal
2905 Context = self.decimal.Context
2906
2907 c = Context()
2908 d = c.copy_abs(Decimal(-1))
2909 self.assertEqual(c.copy_abs(-1), d)
2910 self.assertRaises(TypeError, c.copy_abs, '-1')
2911
2912 def test_copy_decimal(self):
2913 Decimal = self.decimal.Decimal
2914 Context = self.decimal.Context
2915
2916 c = Context()
2917 d = c.copy_decimal(Decimal(-1))
2918 self.assertEqual(c.copy_decimal(-1), d)
2919 self.assertRaises(TypeError, c.copy_decimal, '-1')
2920
2921 def test_copy_negate(self):
2922 Decimal = self.decimal.Decimal
2923 Context = self.decimal.Context
2924
2925 c = Context()
2926 d = c.copy_negate(Decimal(-1))
2927 self.assertEqual(c.copy_negate(-1), d)
2928 self.assertRaises(TypeError, c.copy_negate, '-1')
2929
2930 def test_copy_sign(self):
2931 Decimal = self.decimal.Decimal
2932 Context = self.decimal.Context
2933
2934 c = Context()
2935 d = c.copy_sign(Decimal(1), Decimal(-2))
2936 self.assertEqual(c.copy_sign(1, -2), d)
2937 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2938 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2939 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2940 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2941
2942 def test_divide(self):
2943 Decimal = self.decimal.Decimal
2944 Context = self.decimal.Context
2945
2946 c = Context()
2947 d = c.divide(Decimal(1), Decimal(2))
2948 self.assertEqual(c.divide(1, 2), d)
2949 self.assertEqual(c.divide(Decimal(1), 2), d)
2950 self.assertEqual(c.divide(1, Decimal(2)), d)
2951 self.assertRaises(TypeError, c.divide, '1', 2)
2952 self.assertRaises(TypeError, c.divide, 1, '2')
2953
2954 def test_divide_int(self):
2955 Decimal = self.decimal.Decimal
2956 Context = self.decimal.Context
2957
2958 c = Context()
2959 d = c.divide_int(Decimal(1), Decimal(2))
2960 self.assertEqual(c.divide_int(1, 2), d)
2961 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2962 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2963 self.assertRaises(TypeError, c.divide_int, '1', 2)
2964 self.assertRaises(TypeError, c.divide_int, 1, '2')
2965
2966 def test_divmod(self):
2967 Decimal = self.decimal.Decimal
2968 Context = self.decimal.Context
2969
2970 c = Context()
2971 d = c.divmod(Decimal(1), Decimal(2))
2972 self.assertEqual(c.divmod(1, 2), d)
2973 self.assertEqual(c.divmod(Decimal(1), 2), d)
2974 self.assertEqual(c.divmod(1, Decimal(2)), d)
2975 self.assertRaises(TypeError, c.divmod, '1', 2)
2976 self.assertRaises(TypeError, c.divmod, 1, '2')
2977
2978 def test_exp(self):
2979 Decimal = self.decimal.Decimal
2980 Context = self.decimal.Context
2981
2982 c = Context()
2983 d = c.exp(Decimal(10))
2984 self.assertEqual(c.exp(10), d)
2985 self.assertRaises(TypeError, c.exp, '10')
2986
2987 def test_fma(self):
2988 Decimal = self.decimal.Decimal
2989 Context = self.decimal.Context
2990
2991 c = Context()
2992 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
2993 self.assertEqual(c.fma(2, 3, 4), d)
2994 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
2995 self.assertEqual(c.fma(2, Decimal(3), 4), d)
2996 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
2997 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
2998 self.assertRaises(TypeError, c.fma, '2', 3, 4)
2999 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3000 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3001
3002 # Issue 12079 for Context.fma ...
3003 self.assertRaises(TypeError, c.fma,
3004 Decimal('Infinity'), Decimal(0), "not a decimal")
3005 self.assertRaises(TypeError, c.fma,
3006 Decimal(1), Decimal('snan'), 1.222)
3007 # ... and for Decimal.fma.
3008 self.assertRaises(TypeError, Decimal('Infinity').fma,
3009 Decimal(0), "not a decimal")
3010 self.assertRaises(TypeError, Decimal(1).fma,
3011 Decimal('snan'), 1.222)
3012
3013 def test_is_finite(self):
3014 Decimal = self.decimal.Decimal
3015 Context = self.decimal.Context
3016
3017 c = Context()
3018 d = c.is_finite(Decimal(10))
3019 self.assertEqual(c.is_finite(10), d)
3020 self.assertRaises(TypeError, c.is_finite, '10')
3021
3022 def test_is_infinite(self):
3023 Decimal = self.decimal.Decimal
3024 Context = self.decimal.Context
3025
3026 c = Context()
3027 d = c.is_infinite(Decimal(10))
3028 self.assertEqual(c.is_infinite(10), d)
3029 self.assertRaises(TypeError, c.is_infinite, '10')
3030
3031 def test_is_nan(self):
3032 Decimal = self.decimal.Decimal
3033 Context = self.decimal.Context
3034
3035 c = Context()
3036 d = c.is_nan(Decimal(10))
3037 self.assertEqual(c.is_nan(10), d)
3038 self.assertRaises(TypeError, c.is_nan, '10')
3039
3040 def test_is_normal(self):
3041 Decimal = self.decimal.Decimal
3042 Context = self.decimal.Context
3043
3044 c = Context()
3045 d = c.is_normal(Decimal(10))
3046 self.assertEqual(c.is_normal(10), d)
3047 self.assertRaises(TypeError, c.is_normal, '10')
3048
3049 def test_is_qnan(self):
3050 Decimal = self.decimal.Decimal
3051 Context = self.decimal.Context
3052
3053 c = Context()
3054 d = c.is_qnan(Decimal(10))
3055 self.assertEqual(c.is_qnan(10), d)
3056 self.assertRaises(TypeError, c.is_qnan, '10')
3057
3058 def test_is_signed(self):
3059 Decimal = self.decimal.Decimal
3060 Context = self.decimal.Context
3061
3062 c = Context()
3063 d = c.is_signed(Decimal(10))
3064 self.assertEqual(c.is_signed(10), d)
3065 self.assertRaises(TypeError, c.is_signed, '10')
3066
3067 def test_is_snan(self):
3068 Decimal = self.decimal.Decimal
3069 Context = self.decimal.Context
3070
3071 c = Context()
3072 d = c.is_snan(Decimal(10))
3073 self.assertEqual(c.is_snan(10), d)
3074 self.assertRaises(TypeError, c.is_snan, '10')
3075
3076 def test_is_subnormal(self):
3077 Decimal = self.decimal.Decimal
3078 Context = self.decimal.Context
3079
3080 c = Context()
3081 d = c.is_subnormal(Decimal(10))
3082 self.assertEqual(c.is_subnormal(10), d)
3083 self.assertRaises(TypeError, c.is_subnormal, '10')
3084
3085 def test_is_zero(self):
3086 Decimal = self.decimal.Decimal
3087 Context = self.decimal.Context
3088
3089 c = Context()
3090 d = c.is_zero(Decimal(10))
3091 self.assertEqual(c.is_zero(10), d)
3092 self.assertRaises(TypeError, c.is_zero, '10')
3093
3094 def test_ln(self):
3095 Decimal = self.decimal.Decimal
3096 Context = self.decimal.Context
3097
3098 c = Context()
3099 d = c.ln(Decimal(10))
3100 self.assertEqual(c.ln(10), d)
3101 self.assertRaises(TypeError, c.ln, '10')
3102
3103 def test_log10(self):
3104 Decimal = self.decimal.Decimal
3105 Context = self.decimal.Context
3106
3107 c = Context()
3108 d = c.log10(Decimal(10))
3109 self.assertEqual(c.log10(10), d)
3110 self.assertRaises(TypeError, c.log10, '10')
3111
3112 def test_logb(self):
3113 Decimal = self.decimal.Decimal
3114 Context = self.decimal.Context
3115
3116 c = Context()
3117 d = c.logb(Decimal(10))
3118 self.assertEqual(c.logb(10), d)
3119 self.assertRaises(TypeError, c.logb, '10')
3120
3121 def test_logical_and(self):
3122 Decimal = self.decimal.Decimal
3123 Context = self.decimal.Context
3124
3125 c = Context()
3126 d = c.logical_and(Decimal(1), Decimal(1))
3127 self.assertEqual(c.logical_and(1, 1), d)
3128 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3129 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3130 self.assertRaises(TypeError, c.logical_and, '1', 1)
3131 self.assertRaises(TypeError, c.logical_and, 1, '1')
3132
3133 def test_logical_invert(self):
3134 Decimal = self.decimal.Decimal
3135 Context = self.decimal.Context
3136
3137 c = Context()
3138 d = c.logical_invert(Decimal(1000))
3139 self.assertEqual(c.logical_invert(1000), d)
3140 self.assertRaises(TypeError, c.logical_invert, '1000')
3141
3142 def test_logical_or(self):
3143 Decimal = self.decimal.Decimal
3144 Context = self.decimal.Context
3145
3146 c = Context()
3147 d = c.logical_or(Decimal(1), Decimal(1))
3148 self.assertEqual(c.logical_or(1, 1), d)
3149 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3150 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3151 self.assertRaises(TypeError, c.logical_or, '1', 1)
3152 self.assertRaises(TypeError, c.logical_or, 1, '1')
3153
3154 def test_logical_xor(self):
3155 Decimal = self.decimal.Decimal
3156 Context = self.decimal.Context
3157
3158 c = Context()
3159 d = c.logical_xor(Decimal(1), Decimal(1))
3160 self.assertEqual(c.logical_xor(1, 1), d)
3161 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3162 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3163 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3164 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3165
3166 def test_max(self):
3167 Decimal = self.decimal.Decimal
3168 Context = self.decimal.Context
3169
3170 c = Context()
3171 d = c.max(Decimal(1), Decimal(2))
3172 self.assertEqual(c.max(1, 2), d)
3173 self.assertEqual(c.max(Decimal(1), 2), d)
3174 self.assertEqual(c.max(1, Decimal(2)), d)
3175 self.assertRaises(TypeError, c.max, '1', 2)
3176 self.assertRaises(TypeError, c.max, 1, '2')
3177
3178 def test_max_mag(self):
3179 Decimal = self.decimal.Decimal
3180 Context = self.decimal.Context
3181
3182 c = Context()
3183 d = c.max_mag(Decimal(1), Decimal(2))
3184 self.assertEqual(c.max_mag(1, 2), d)
3185 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3186 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3187 self.assertRaises(TypeError, c.max_mag, '1', 2)
3188 self.assertRaises(TypeError, c.max_mag, 1, '2')
3189
3190 def test_min(self):
3191 Decimal = self.decimal.Decimal
3192 Context = self.decimal.Context
3193
3194 c = Context()
3195 d = c.min(Decimal(1), Decimal(2))
3196 self.assertEqual(c.min(1, 2), d)
3197 self.assertEqual(c.min(Decimal(1), 2), d)
3198 self.assertEqual(c.min(1, Decimal(2)), d)
3199 self.assertRaises(TypeError, c.min, '1', 2)
3200 self.assertRaises(TypeError, c.min, 1, '2')
3201
3202 def test_min_mag(self):
3203 Decimal = self.decimal.Decimal
3204 Context = self.decimal.Context
3205
3206 c = Context()
3207 d = c.min_mag(Decimal(1), Decimal(2))
3208 self.assertEqual(c.min_mag(1, 2), d)
3209 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3210 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3211 self.assertRaises(TypeError, c.min_mag, '1', 2)
3212 self.assertRaises(TypeError, c.min_mag, 1, '2')
3213
3214 def test_minus(self):
3215 Decimal = self.decimal.Decimal
3216 Context = self.decimal.Context
3217
3218 c = Context()
3219 d = c.minus(Decimal(10))
3220 self.assertEqual(c.minus(10), d)
3221 self.assertRaises(TypeError, c.minus, '10')
3222
3223 def test_multiply(self):
3224 Decimal = self.decimal.Decimal
3225 Context = self.decimal.Context
3226
3227 c = Context()
3228 d = c.multiply(Decimal(1), Decimal(2))
3229 self.assertEqual(c.multiply(1, 2), d)
3230 self.assertEqual(c.multiply(Decimal(1), 2), d)
3231 self.assertEqual(c.multiply(1, Decimal(2)), d)
3232 self.assertRaises(TypeError, c.multiply, '1', 2)
3233 self.assertRaises(TypeError, c.multiply, 1, '2')
3234
3235 def test_next_minus(self):
3236 Decimal = self.decimal.Decimal
3237 Context = self.decimal.Context
3238
3239 c = Context()
3240 d = c.next_minus(Decimal(10))
3241 self.assertEqual(c.next_minus(10), d)
3242 self.assertRaises(TypeError, c.next_minus, '10')
3243
3244 def test_next_plus(self):
3245 Decimal = self.decimal.Decimal
3246 Context = self.decimal.Context
3247
3248 c = Context()
3249 d = c.next_plus(Decimal(10))
3250 self.assertEqual(c.next_plus(10), d)
3251 self.assertRaises(TypeError, c.next_plus, '10')
3252
3253 def test_next_toward(self):
3254 Decimal = self.decimal.Decimal
3255 Context = self.decimal.Context
3256
3257 c = Context()
3258 d = c.next_toward(Decimal(1), Decimal(2))
3259 self.assertEqual(c.next_toward(1, 2), d)
3260 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3261 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3262 self.assertRaises(TypeError, c.next_toward, '1', 2)
3263 self.assertRaises(TypeError, c.next_toward, 1, '2')
3264
3265 def test_normalize(self):
3266 Decimal = self.decimal.Decimal
3267 Context = self.decimal.Context
3268
3269 c = Context()
3270 d = c.normalize(Decimal(10))
3271 self.assertEqual(c.normalize(10), d)
3272 self.assertRaises(TypeError, c.normalize, '10')
3273
3274 def test_number_class(self):
3275 Decimal = self.decimal.Decimal
3276 Context = self.decimal.Context
3277
3278 c = Context()
3279 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3280 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3281 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3282
3283 def test_plus(self):
3284 Decimal = self.decimal.Decimal
3285 Context = self.decimal.Context
3286
3287 c = Context()
3288 d = c.plus(Decimal(10))
3289 self.assertEqual(c.plus(10), d)
3290 self.assertRaises(TypeError, c.plus, '10')
3291
3292 def test_power(self):
3293 Decimal = self.decimal.Decimal
3294 Context = self.decimal.Context
3295
3296 c = Context()
3297 d = c.power(Decimal(1), Decimal(4))
3298 self.assertEqual(c.power(1, 4), d)
3299 self.assertEqual(c.power(Decimal(1), 4), d)
3300 self.assertEqual(c.power(1, Decimal(4)), d)
3301 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3302 self.assertRaises(TypeError, c.power, '1', 4)
3303 self.assertRaises(TypeError, c.power, 1, '4')
3304 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3305
3306 def test_quantize(self):
3307 Decimal = self.decimal.Decimal
3308 Context = self.decimal.Context
3309
3310 c = Context()
3311 d = c.quantize(Decimal(1), Decimal(2))
3312 self.assertEqual(c.quantize(1, 2), d)
3313 self.assertEqual(c.quantize(Decimal(1), 2), d)
3314 self.assertEqual(c.quantize(1, Decimal(2)), d)
3315 self.assertRaises(TypeError, c.quantize, '1', 2)
3316 self.assertRaises(TypeError, c.quantize, 1, '2')
3317
3318 def test_remainder(self):
3319 Decimal = self.decimal.Decimal
3320 Context = self.decimal.Context
3321
3322 c = Context()
3323 d = c.remainder(Decimal(1), Decimal(2))
3324 self.assertEqual(c.remainder(1, 2), d)
3325 self.assertEqual(c.remainder(Decimal(1), 2), d)
3326 self.assertEqual(c.remainder(1, Decimal(2)), d)
3327 self.assertRaises(TypeError, c.remainder, '1', 2)
3328 self.assertRaises(TypeError, c.remainder, 1, '2')
3329
3330 def test_remainder_near(self):
3331 Decimal = self.decimal.Decimal
3332 Context = self.decimal.Context
3333
3334 c = Context()
3335 d = c.remainder_near(Decimal(1), Decimal(2))
3336 self.assertEqual(c.remainder_near(1, 2), d)
3337 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3338 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3339 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3340 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3341
3342 def test_rotate(self):
3343 Decimal = self.decimal.Decimal
3344 Context = self.decimal.Context
3345
3346 c = Context()
3347 d = c.rotate(Decimal(1), Decimal(2))
3348 self.assertEqual(c.rotate(1, 2), d)
3349 self.assertEqual(c.rotate(Decimal(1), 2), d)
3350 self.assertEqual(c.rotate(1, Decimal(2)), d)
3351 self.assertRaises(TypeError, c.rotate, '1', 2)
3352 self.assertRaises(TypeError, c.rotate, 1, '2')
3353
3354 def test_sqrt(self):
3355 Decimal = self.decimal.Decimal
3356 Context = self.decimal.Context
3357
3358 c = Context()
3359 d = c.sqrt(Decimal(10))
3360 self.assertEqual(c.sqrt(10), d)
3361 self.assertRaises(TypeError, c.sqrt, '10')
3362
3363 def test_same_quantum(self):
3364 Decimal = self.decimal.Decimal
3365 Context = self.decimal.Context
3366
3367 c = Context()
3368 d = c.same_quantum(Decimal(1), Decimal(2))
3369 self.assertEqual(c.same_quantum(1, 2), d)
3370 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3371 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3372 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3373 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3374
3375 def test_scaleb(self):
3376 Decimal = self.decimal.Decimal
3377 Context = self.decimal.Context
3378
3379 c = Context()
3380 d = c.scaleb(Decimal(1), Decimal(2))
3381 self.assertEqual(c.scaleb(1, 2), d)
3382 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3383 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3384 self.assertRaises(TypeError, c.scaleb, '1', 2)
3385 self.assertRaises(TypeError, c.scaleb, 1, '2')
3386
3387 def test_shift(self):
3388 Decimal = self.decimal.Decimal
3389 Context = self.decimal.Context
3390
3391 c = Context()
3392 d = c.shift(Decimal(1), Decimal(2))
3393 self.assertEqual(c.shift(1, 2), d)
3394 self.assertEqual(c.shift(Decimal(1), 2), d)
3395 self.assertEqual(c.shift(1, Decimal(2)), d)
3396 self.assertRaises(TypeError, c.shift, '1', 2)
3397 self.assertRaises(TypeError, c.shift, 1, '2')
3398
3399 def test_subtract(self):
3400 Decimal = self.decimal.Decimal
3401 Context = self.decimal.Context
3402
3403 c = Context()
3404 d = c.subtract(Decimal(1), Decimal(2))
3405 self.assertEqual(c.subtract(1, 2), d)
3406 self.assertEqual(c.subtract(Decimal(1), 2), d)
3407 self.assertEqual(c.subtract(1, Decimal(2)), d)
3408 self.assertRaises(TypeError, c.subtract, '1', 2)
3409 self.assertRaises(TypeError, c.subtract, 1, '2')
3410
3411 def test_to_eng_string(self):
3412 Decimal = self.decimal.Decimal
3413 Context = self.decimal.Context
3414
3415 c = Context()
3416 d = c.to_eng_string(Decimal(10))
3417 self.assertEqual(c.to_eng_string(10), d)
3418 self.assertRaises(TypeError, c.to_eng_string, '10')
3419
3420 def test_to_sci_string(self):
3421 Decimal = self.decimal.Decimal
3422 Context = self.decimal.Context
3423
3424 c = Context()
3425 d = c.to_sci_string(Decimal(10))
3426 self.assertEqual(c.to_sci_string(10), d)
3427 self.assertRaises(TypeError, c.to_sci_string, '10')
3428
3429 def test_to_integral_exact(self):
3430 Decimal = self.decimal.Decimal
3431 Context = self.decimal.Context
3432
3433 c = Context()
3434 d = c.to_integral_exact(Decimal(10))
3435 self.assertEqual(c.to_integral_exact(10), d)
3436 self.assertRaises(TypeError, c.to_integral_exact, '10')
3437
3438 def test_to_integral_value(self):
3439 Decimal = self.decimal.Decimal
3440 Context = self.decimal.Context
3441
3442 c = Context()
3443 d = c.to_integral_value(Decimal(10))
3444 self.assertEqual(c.to_integral_value(10), d)
3445 self.assertRaises(TypeError, c.to_integral_value, '10')
3446 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3447
3448class CContextAPItests(ContextAPItests):
3449 decimal = C
3450class PyContextAPItests(ContextAPItests):
3451 decimal = P
3452
3453class ContextWithStatement(unittest.TestCase):
3454 # Can't do these as docstrings until Python 2.6
3455 # as doctest can't handle __future__ statements
3456
3457 def test_localcontext(self):
3458 # Use a copy of the current context in the block
3459 getcontext = self.decimal.getcontext
3460 localcontext = self.decimal.localcontext
3461
3462 orig_ctx = getcontext()
3463 with localcontext() as enter_ctx:
3464 set_ctx = getcontext()
3465 final_ctx = getcontext()
3466 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3467 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3468 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3469
3470 def test_localcontextarg(self):
3471 # Use a copy of the supplied context in the block
3472 Context = self.decimal.Context
3473 getcontext = self.decimal.getcontext
3474 localcontext = self.decimal.localcontext
3475
3476 localcontext = self.decimal.localcontext
3477 orig_ctx = getcontext()
3478 new_ctx = Context(prec=42)
3479 with localcontext(new_ctx) as enter_ctx:
3480 set_ctx = getcontext()
3481 final_ctx = getcontext()
3482 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3483 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3484 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3485 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3486
3487 def test_nested_with_statements(self):
3488 # Use a copy of the supplied context in the block
3489 Decimal = self.decimal.Decimal
3490 Context = self.decimal.Context
3491 getcontext = self.decimal.getcontext
3492 localcontext = self.decimal.localcontext
3493 Clamped = self.decimal.Clamped
3494 Overflow = self.decimal.Overflow
3495
3496 orig_ctx = getcontext()
3497 orig_ctx.clear_flags()
3498 new_ctx = Context(Emax=384)
3499 with localcontext() as c1:
3500 self.assertEqual(c1.flags, orig_ctx.flags)
3501 self.assertEqual(c1.traps, orig_ctx.traps)
3502 c1.traps[Clamped] = True
3503 c1.Emin = -383
3504 self.assertNotEqual(orig_ctx.Emin, -383)
3505 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3506 self.assertTrue(c1.flags[Clamped])
3507 with localcontext(new_ctx) as c2:
3508 self.assertEqual(c2.flags, new_ctx.flags)
3509 self.assertEqual(c2.traps, new_ctx.traps)
3510 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3511 self.assertFalse(c2.flags[Clamped])
3512 self.assertTrue(c2.flags[Overflow])
3513 del c2
3514 self.assertFalse(c1.flags[Overflow])
3515 del c1
3516 self.assertNotEqual(orig_ctx.Emin, -383)
3517 self.assertFalse(orig_ctx.flags[Clamped])
3518 self.assertFalse(orig_ctx.flags[Overflow])
3519 self.assertFalse(new_ctx.flags[Clamped])
3520 self.assertFalse(new_ctx.flags[Overflow])
3521
3522 def test_with_statements_gc1(self):
3523 localcontext = self.decimal.localcontext
3524
3525 with localcontext() as c1:
3526 del c1
3527 with localcontext() as c2:
3528 del c2
3529 with localcontext() as c3:
3530 del c3
3531 with localcontext() as c4:
3532 del c4
3533
3534 def test_with_statements_gc2(self):
3535 localcontext = self.decimal.localcontext
3536
3537 with localcontext() as c1:
3538 with localcontext(c1) as c2:
3539 del c1
3540 with localcontext(c2) as c3:
3541 del c2
3542 with localcontext(c3) as c4:
3543 del c3
3544 del c4
3545
3546 def test_with_statements_gc3(self):
3547 Context = self.decimal.Context
3548 localcontext = self.decimal.localcontext
3549 getcontext = self.decimal.getcontext
3550 setcontext = self.decimal.setcontext
3551
3552 with localcontext() as c1:
3553 del c1
3554 n1 = Context(prec=1)
3555 setcontext(n1)
3556 with localcontext(n1) as c2:
3557 del n1
3558 self.assertEqual(c2.prec, 1)
3559 del c2
3560 n2 = Context(prec=2)
3561 setcontext(n2)
3562 del n2
3563 self.assertEqual(getcontext().prec, 2)
3564 n3 = Context(prec=3)
3565 setcontext(n3)
3566 self.assertEqual(getcontext().prec, 3)
3567 with localcontext(n3) as c3:
3568 del n3
3569 self.assertEqual(c3.prec, 3)
3570 del c3
3571 n4 = Context(prec=4)
3572 setcontext(n4)
3573 del n4
3574 self.assertEqual(getcontext().prec, 4)
3575 with localcontext() as c4:
3576 self.assertEqual(c4.prec, 4)
3577 del c4
3578
3579class CContextWithStatement(ContextWithStatement):
3580 decimal = C
3581class PyContextWithStatement(ContextWithStatement):
3582 decimal = P
3583
3584class ContextFlags(unittest.TestCase):
3585
3586 def test_flags_irrelevant(self):
3587 # check that the result (numeric result + flags raised) of an
3588 # arithmetic operation doesn't depend on the current flags
3589 Decimal = self.decimal.Decimal
3590 Context = self.decimal.Context
3591 Inexact = self.decimal.Inexact
3592 Rounded = self.decimal.Rounded
3593 Underflow = self.decimal.Underflow
3594 Clamped = self.decimal.Clamped
3595 Subnormal = self.decimal.Subnormal
3596 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
3597
3598 def raise_error(context, flag):
3599 if self.decimal == C:
3600 context.flags[flag] = True
3601 if context.traps[flag]:
3602 raise flag
3603 else:
3604 context._raise_error(flag)
3605
3606 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3607 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3608
3609 # operations that raise various flags, in the form (function, arglist)
3610 operations = [
3611 (context._apply, [Decimal("100E-425000010")]),
3612 (context.sqrt, [Decimal(2)]),
3613 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3614 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3615 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3616 ]
3617
3618 # try various flags individually, then a whole lot at once
3619 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3620 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3621
3622 for fn, args in operations:
3623 # find answer and flags raised using a clean context
3624 context.clear_flags()
3625 ans = fn(*args)
3626 flags = [k for k, v in context.flags.items() if v]
3627
3628 for extra_flags in flagsets:
3629 # set flags, before calling operation
3630 context.clear_flags()
3631 for flag in extra_flags:
3632 raise_error(context, flag)
3633 new_ans = fn(*args)
3634
3635 # flags that we expect to be set after the operation
3636 expected_flags = list(flags)
3637 for flag in extra_flags:
3638 if flag not in expected_flags:
3639 expected_flags.append(flag)
3640 expected_flags.sort(key=id)
3641
3642 # flags we actually got
3643 new_flags = [k for k,v in context.flags.items() if v]
3644 new_flags.sort(key=id)
3645
3646 self.assertEqual(ans, new_ans,
3647 "operation produces different answers depending on flags set: " +
3648 "expected %s, got %s." % (ans, new_ans))
3649 self.assertEqual(new_flags, expected_flags,
3650 "operation raises different flags depending on flags set: " +
3651 "expected %s, got %s" % (expected_flags, new_flags))
3652
3653 def test_flag_comparisons(self):
3654 Context = self.decimal.Context
3655 Inexact = self.decimal.Inexact
3656 Rounded = self.decimal.Rounded
3657
3658 c = Context()
3659
3660 # Valid SignalDict
3661 self.assertNotEqual(c.flags, c.traps)
3662 self.assertNotEqual(c.traps, c.flags)
3663
3664 c.flags = c.traps
3665 self.assertEqual(c.flags, c.traps)
3666 self.assertEqual(c.traps, c.flags)
3667
3668 c.flags[Rounded] = True
3669 c.traps = c.flags
3670 self.assertEqual(c.flags, c.traps)
3671 self.assertEqual(c.traps, c.flags)
3672
3673 d = {}
3674 d.update(c.flags)
3675 self.assertEqual(d, c.flags)
3676 self.assertEqual(c.flags, d)
3677
3678 d[Inexact] = True
3679 self.assertNotEqual(d, c.flags)
3680 self.assertNotEqual(c.flags, d)
3681
3682 # Invalid SignalDict
3683 d = {Inexact:False}
3684 self.assertNotEqual(d, c.flags)
3685 self.assertNotEqual(c.flags, d)
3686
3687 d = ["xyz"]
3688 self.assertNotEqual(d, c.flags)
3689 self.assertNotEqual(c.flags, d)
3690
3691 @requires_IEEE_754
3692 def test_float_operation(self):
3693 Decimal = self.decimal.Decimal
3694 FloatOperation = self.decimal.FloatOperation
3695 localcontext = self.decimal.localcontext
3696
3697 with localcontext() as c:
3698 ##### trap is off by default
3699 self.assertFalse(c.traps[FloatOperation])
3700
3701 # implicit conversion sets the flag
3702 c.clear_flags()
3703 self.assertEqual(Decimal(7.5), 7.5)
3704 self.assertTrue(c.flags[FloatOperation])
3705
3706 c.clear_flags()
3707 self.assertEqual(c.create_decimal(7.5), 7.5)
3708 self.assertTrue(c.flags[FloatOperation])
3709
3710 # explicit conversion does not set the flag
3711 c.clear_flags()
3712 x = Decimal.from_float(7.5)
3713 self.assertFalse(c.flags[FloatOperation])
3714 # comparison sets the flag
3715 self.assertEqual(x, 7.5)
3716 self.assertTrue(c.flags[FloatOperation])
3717
3718 c.clear_flags()
3719 x = c.create_decimal_from_float(7.5)
3720 self.assertFalse(c.flags[FloatOperation])
3721 self.assertEqual(x, 7.5)
3722 self.assertTrue(c.flags[FloatOperation])
3723
3724 ##### set the trap
3725 c.traps[FloatOperation] = True
3726
3727 # implicit conversion raises
3728 c.clear_flags()
3729 self.assertRaises(FloatOperation, Decimal, 7.5)
3730 self.assertTrue(c.flags[FloatOperation])
3731
3732 c.clear_flags()
3733 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3734 self.assertTrue(c.flags[FloatOperation])
3735
3736 # explicit conversion is silent
3737 c.clear_flags()
3738 x = Decimal.from_float(7.5)
3739 self.assertFalse(c.flags[FloatOperation])
3740
3741 c.clear_flags()
3742 x = c.create_decimal_from_float(7.5)
3743 self.assertFalse(c.flags[FloatOperation])
3744
3745 def test_float_comparison(self):
3746 Decimal = self.decimal.Decimal
3747 Context = self.decimal.Context
3748 FloatOperation = self.decimal.FloatOperation
3749 localcontext = self.decimal.localcontext
3750
3751 def assert_attr(a, b, attr, context, signal=None):
3752 context.clear_flags()
3753 f = getattr(a, attr)
3754 if signal == FloatOperation:
3755 self.assertRaises(signal, f, b)
3756 else:
3757 self.assertIs(f(b), True)
3758 self.assertTrue(context.flags[FloatOperation])
3759
3760 small_d = Decimal('0.25')
3761 big_d = Decimal('3.0')
3762 small_f = 0.25
3763 big_f = 3.0
3764
3765 zero_d = Decimal('0.0')
3766 neg_zero_d = Decimal('-0.0')
3767 zero_f = 0.0
3768 neg_zero_f = -0.0
3769
3770 inf_d = Decimal('Infinity')
3771 neg_inf_d = Decimal('-Infinity')
3772 inf_f = float('inf')
3773 neg_inf_f = float('-inf')
3774
3775 def doit(c, signal=None):
3776 # Order
3777 for attr in '__lt__', '__le__':
3778 assert_attr(small_d, big_f, attr, c, signal)
3779
3780 for attr in '__gt__', '__ge__':
3781 assert_attr(big_d, small_f, attr, c, signal)
3782
3783 # Equality
3784 assert_attr(small_d, small_f, '__eq__', c, None)
3785
3786 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3787 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3788
3789 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3790 assert_attr(zero_d, zero_f, '__eq__', c, None)
3791
3792 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3793 assert_attr(inf_d, inf_f, '__eq__', c, None)
3794
3795 # Inequality
3796 assert_attr(small_d, big_f, '__ne__', c, None)
3797
3798 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3799
3800 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3801 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3802
3803 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3804
3805 def test_containers(c, signal=None):
3806 c.clear_flags()
3807 s = set([100.0, Decimal('100.0')])
3808 self.assertEqual(len(s), 1)
3809 self.assertTrue(c.flags[FloatOperation])
3810
3811 c.clear_flags()
3812 if signal:
3813 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3814 else:
3815 s = sorted([10.0, Decimal('10.0')])
3816 self.assertTrue(c.flags[FloatOperation])
3817
3818 c.clear_flags()
3819 b = 10.0 in [Decimal('10.0'), 1.0]
3820 self.assertTrue(c.flags[FloatOperation])
3821
3822 c.clear_flags()
3823 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3824 self.assertTrue(c.flags[FloatOperation])
3825
3826 nc = Context()
3827 with localcontext(nc) as c:
3828 self.assertFalse(c.traps[FloatOperation])
3829 doit(c, signal=None)
3830 test_containers(c, signal=None)
3831
3832 c.traps[FloatOperation] = True
3833 doit(c, signal=FloatOperation)
3834 test_containers(c, signal=FloatOperation)
3835
3836 def test_float_operation_default(self):
3837 Decimal = self.decimal.Decimal
3838 Context = self.decimal.Context
3839 Inexact = self.decimal.Inexact
3840 FloatOperation= self.decimal.FloatOperation
3841
3842 context = Context()
3843 self.assertFalse(context.flags[FloatOperation])
3844 self.assertFalse(context.traps[FloatOperation])
3845
3846 context.clear_traps()
3847 context.traps[Inexact] = True
3848 context.traps[FloatOperation] = True
3849 self.assertTrue(context.traps[FloatOperation])
3850 self.assertTrue(context.traps[Inexact])
3851
3852class CContextFlags(ContextFlags):
3853 decimal = C
3854class PyContextFlags(ContextFlags):
3855 decimal = P
3856
3857class SpecialContexts(unittest.TestCase):
3858 """Test the context templates."""
3859
3860 def test_context_templates(self):
3861 BasicContext = self.decimal.BasicContext
3862 ExtendedContext = self.decimal.ExtendedContext
3863 getcontext = self.decimal.getcontext
3864 setcontext = self.decimal.setcontext
3865 InvalidOperation = self.decimal.InvalidOperation
3866 DivisionByZero = self.decimal.DivisionByZero
3867 Overflow = self.decimal.Overflow
3868 Underflow = self.decimal.Underflow
3869 Clamped = self.decimal.Clamped
3870
3871 assert_signals(self, BasicContext, 'traps',
3872 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3873 )
3874
3875 savecontext = getcontext().copy()
3876 basic_context_prec = BasicContext.prec
3877 extended_context_prec = ExtendedContext.prec
3878
3879 ex = None
3880 try:
3881 BasicContext.prec = ExtendedContext.prec = 441
3882 for template in BasicContext, ExtendedContext:
3883 setcontext(template)
3884 c = getcontext()
3885 self.assertIsNot(c, template)
3886 self.assertEqual(c.prec, 441)
3887 except Exception as e:
3888 ex = e.__class__
3889 finally:
3890 BasicContext.prec = basic_context_prec
3891 ExtendedContext.prec = extended_context_prec
3892 setcontext(savecontext)
3893 if ex:
3894 raise ex
3895
3896 def test_default_context(self):
3897 DefaultContext = self.decimal.DefaultContext
3898 BasicContext = self.decimal.BasicContext
3899 ExtendedContext = self.decimal.ExtendedContext
3900 getcontext = self.decimal.getcontext
3901 setcontext = self.decimal.setcontext
3902 InvalidOperation = self.decimal.InvalidOperation
3903 DivisionByZero = self.decimal.DivisionByZero
3904 Overflow = self.decimal.Overflow
3905
3906 self.assertEqual(BasicContext.prec, 9)
3907 self.assertEqual(ExtendedContext.prec, 9)
3908
3909 assert_signals(self, DefaultContext, 'traps',
3910 [InvalidOperation, DivisionByZero, Overflow]
3911 )
3912
3913 savecontext = getcontext().copy()
3914 default_context_prec = DefaultContext.prec
3915
3916 ex = None
3917 try:
3918 c = getcontext()
3919 saveprec = c.prec
3920
3921 DefaultContext.prec = 961
3922 c = getcontext()
3923 self.assertEqual(c.prec, saveprec)
3924
3925 setcontext(DefaultContext)
3926 c = getcontext()
3927 self.assertIsNot(c, DefaultContext)
3928 self.assertEqual(c.prec, 961)
3929 except Exception as e:
3930 ex = e.__class__
3931 finally:
3932 DefaultContext.prec = default_context_prec
3933 setcontext(savecontext)
3934 if ex:
3935 raise ex
3936
3937class CSpecialContexts(SpecialContexts):
3938 decimal = C
3939class PySpecialContexts(SpecialContexts):
3940 decimal = P
3941
3942class ContextInputValidation(unittest.TestCase):
3943
3944 def test_invalid_context(self):
3945 Context = self.decimal.Context
3946 DefaultContext = self.decimal.DefaultContext
3947
3948 c = DefaultContext.copy()
3949
3950 # prec, Emax
3951 for attr in ['prec', 'Emax']:
3952 setattr(c, attr, 999999)
3953 self.assertEqual(getattr(c, attr), 999999)
3954 self.assertRaises(ValueError, setattr, c, attr, -1)
3955 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3956
3957 # Emin
3958 setattr(c, 'Emin', -999999)
3959 self.assertEqual(getattr(c, 'Emin'), -999999)
3960 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3961 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3962
3963 # rounding: always raise TypeError in order to get consistent
3964 # exceptions across implementations. In decimal, rounding
3965 # modes are strings, in _decimal they are integers. The idea
3966 # is to view rounding as an abstract type and not mind the
3967 # implementation details.
3968 # Hence, a user should view the rounding modes as if they
3969 # had been defined in a language that supports abstract
3970 # data types, e.g. ocaml:
3971 #
3972 # type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;;
3973 #
3974 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3975 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3976 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3977 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3978
3979 # capitals, clamp
3980 for attr in ['capitals', 'clamp']:
3981 self.assertRaises(ValueError, setattr, c, attr, -1)
3982 self.assertRaises(ValueError, setattr, c, attr, 2)
3983 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3984
3985 # Invalid attribute
3986 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3987
3988 # Invalid signal dict
3989 self.assertRaises(TypeError, setattr, c, 'flags', [])
3990 self.assertRaises(KeyError, setattr, c, 'flags', {})
3991 self.assertRaises(KeyError, setattr, c, 'traps',
3992 {'InvalidOperation':0})
3993
3994 # Attributes cannot be deleted
3995 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3996 'flags', 'traps']:
3997 self.assertRaises(AttributeError, c.__delattr__, attr)
3998
3999 # Invalid attributes
4000 self.assertRaises(TypeError, getattr, c, 9)
4001 self.assertRaises(TypeError, setattr, c, 9)
4002
4003 # Invalid values in constructor
4004 self.assertRaises(TypeError, Context, rounding=999999)
4005 self.assertRaises(TypeError, Context, rounding='xyz')
4006 self.assertRaises(ValueError, Context, clamp=2)
4007 self.assertRaises(ValueError, Context, capitals=-1)
4008 self.assertRaises(KeyError, Context, flags=["P"])
4009 self.assertRaises(KeyError, Context, traps=["Q"])
4010
4011 # Type error in conversion
4012 self.assertRaises(TypeError, Context, flags=(0,1))
4013 self.assertRaises(TypeError, Context, traps=(1,0))
4014
4015class CContextInputValidation(ContextInputValidation):
4016 decimal = C
4017class PyContextInputValidation(ContextInputValidation):
4018 decimal = P
4019
4020class ContextSubclassing(unittest.TestCase):
4021
4022 def test_context_subclassing(self):
4023 decimal = self.decimal
4024 Decimal = decimal.Decimal
4025 Context = decimal.Context
4026 ROUND_HALF_EVEN = decimal.ROUND_HALF_EVEN
4027 ROUND_DOWN = decimal.ROUND_DOWN
4028 Clamped = decimal.Clamped
4029 DivisionByZero = decimal.DivisionByZero
4030 Inexact = decimal.Inexact
4031 Overflow = decimal.Overflow
4032 Rounded = decimal.Rounded
4033 Subnormal = decimal.Subnormal
4034 Underflow = decimal.Underflow
4035 InvalidOperation = decimal.InvalidOperation
4036
4037 class MyContext(Context):
4038 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4039 capitals=None, clamp=None, flags=None,
4040 traps=None):
4041 Context.__init__(self)
4042 if prec is not None:
4043 self.prec = prec
4044 if rounding is not None:
4045 self.rounding = rounding
4046 if Emin is not None:
4047 self.Emin = Emin
4048 if Emax is not None:
4049 self.Emax = Emax
4050 if capitals is not None:
4051 self.capitals = capitals
4052 if clamp is not None:
4053 self.clamp = clamp
4054 if flags is not None:
4055 if isinstance(flags, list):
4056 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4057 self.flags = flags
4058 if traps is not None:
4059 if isinstance(traps, list):
4060 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4061 self.traps = traps
4062
4063 c = Context()
4064 d = MyContext()
4065 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4066 'flags', 'traps'):
4067 self.assertEqual(getattr(c, attr), getattr(d, attr))
4068
4069 # prec
4070 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4071 c = MyContext(prec=1)
4072 self.assertEqual(c.prec, 1)
4073 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4074
4075 # rounding
4076 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4077 c = MyContext(rounding=ROUND_DOWN, prec=1)
4078 self.assertEqual(c.rounding, ROUND_DOWN)
4079 self.assertEqual(c.plus(Decimal('9.9')), 9)
4080
4081 # Emin
4082 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4083 c = MyContext(Emin=-1, prec=1)
4084 self.assertEqual(c.Emin, -1)
4085 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4086 self.assertEqual(x, Decimal('0.0'))
4087 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4088 self.assertTrue(c.flags[signal])
4089
4090 # Emax
4091 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4092 c = MyContext(Emax=1, prec=1)
4093 self.assertEqual(c.Emax, 1)
4094 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4095 if self.decimal == C:
4096 for signal in (Inexact, Overflow, Rounded):
4097 self.assertTrue(c.flags[signal])
4098
4099 # capitals
4100 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4101 c = MyContext(capitals=0)
4102 self.assertEqual(c.capitals, 0)
4103 x = c.create_decimal('1E222')
4104 self.assertEqual(c.to_sci_string(x), '1e+222')
4105
4106 # clamp
4107 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4108 c = MyContext(clamp=1, Emax=99)
4109 self.assertEqual(c.clamp, 1)
4110 x = c.plus(Decimal('1e99'))
4111 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4112
4113 # flags
4114 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4115 c = MyContext(flags=[Rounded, DivisionByZero])
4116 for signal in (Rounded, DivisionByZero):
4117 self.assertTrue(c.flags[signal])
4118 c.clear_flags()
4119 for signal in OrderedSignals[decimal]:
4120 self.assertFalse(c.flags[signal])
4121
4122 # traps
4123 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4124 c = MyContext(traps=[Rounded, DivisionByZero])
4125 for signal in (Rounded, DivisionByZero):
4126 self.assertTrue(c.traps[signal])
4127 c.clear_traps()
4128 for signal in OrderedSignals[decimal]:
4129 self.assertFalse(c.traps[signal])
4130
4131class CContextSubclassing(ContextSubclassing):
4132 decimal = C
4133class PyContextSubclassing(ContextSubclassing):
4134 decimal = P
4135
4136@skip_if_extra_functionality
4137class CheckAttributes(unittest.TestCase):
4138
4139 def test_module_attributes(self):
4140
4141 # Architecture dependent context limits
4142 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4143 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4144 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4145 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4146
4147 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4148 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4149
4150 self.assertEqual(C.__version__, P.__version__)
4151
4152 x = dir(C)
4153 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02004154 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004155
4156 def test_context_attributes(self):
4157
4158 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4159 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4160 self.assertEqual(set(x) - set(y), set())
4161
4162 def test_decimal_attributes(self):
4163
4164 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4165 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4166 self.assertEqual(set(x) - set(y), set())
4167
4168class Coverage(unittest.TestCase):
4169
4170 def test_adjusted(self):
4171 Decimal = self.decimal.Decimal
4172
4173 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4174 # XXX raise?
4175 self.assertEqual(Decimal('nan').adjusted(), 0)
4176 self.assertEqual(Decimal('inf').adjusted(), 0)
4177
4178 def test_canonical(self):
4179 Decimal = self.decimal.Decimal
4180 getcontext = self.decimal.getcontext
4181
4182 x = Decimal(9).canonical()
4183 self.assertEqual(x, 9)
4184
4185 c = getcontext()
4186 x = c.canonical(Decimal(9))
4187 self.assertEqual(x, 9)
4188
4189 def test_context_repr(self):
4190 c = self.decimal.DefaultContext.copy()
4191
4192 c.prec = 425000000
4193 c.Emax = 425000000
4194 c.Emin = -425000000
4195 c.rounding = self.decimal.ROUND_HALF_DOWN
4196 c.capitals = 0
4197 c.clamp = 1
4198 for sig in OrderedSignals[self.decimal]:
4199 c.flags[sig] = False
4200 c.traps[sig] = False
4201
4202 s = c.__repr__()
4203 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4204 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4205 "flags=[], traps=[])"
4206 self.assertEqual(s, t)
4207
4208 def test_implicit_context(self):
4209 Decimal = self.decimal.Decimal
4210 localcontext = self.decimal.localcontext
4211
4212 with localcontext() as c:
4213 c.prec = 1
4214 c.Emax = 1
4215 c.Emin = -1
4216
4217 # abs
4218 self.assertEqual(abs(Decimal("-10")), 10)
4219 # add
4220 self.assertEqual(Decimal("7") + 1, 8)
4221 # divide
4222 self.assertEqual(Decimal("10") / 5, 2)
4223 # divide_int
4224 self.assertEqual(Decimal("10") // 7, 1)
4225 # fma
4226 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4227 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4228 # three arg power
4229 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4230 # exp
4231 self.assertEqual(Decimal("1.01").exp(), 3)
4232 # is_normal
4233 self.assertIs(Decimal("0.01").is_normal(), False)
4234 # is_subnormal
4235 self.assertIs(Decimal("0.01").is_subnormal(), True)
4236 # ln
4237 self.assertEqual(Decimal("20").ln(), 3)
4238 # log10
4239 self.assertEqual(Decimal("20").log10(), 1)
4240 # logb
4241 self.assertEqual(Decimal("580").logb(), 2)
4242 # logical_invert
4243 self.assertEqual(Decimal("10").logical_invert(), 1)
4244 # minus
4245 self.assertEqual(-Decimal("-10"), 10)
4246 # multiply
4247 self.assertEqual(Decimal("2") * 4, 8)
4248 # next_minus
4249 self.assertEqual(Decimal("10").next_minus(), 9)
4250 # next_plus
4251 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4252 # normalize
4253 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4254 # number_class
4255 self.assertEqual(Decimal("10").number_class(), '+Normal')
4256 # plus
4257 self.assertEqual(+Decimal("-1"), -1)
4258 # remainder
4259 self.assertEqual(Decimal("10") % 7, 3)
4260 # subtract
4261 self.assertEqual(Decimal("10") - 7, 3)
4262 # to_integral_exact
4263 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4264
4265 # Boolean functions
4266 self.assertTrue(Decimal("1").is_canonical())
4267 self.assertTrue(Decimal("1").is_finite())
4268 self.assertTrue(Decimal("1").is_finite())
4269 self.assertTrue(Decimal("snan").is_snan())
4270 self.assertTrue(Decimal("-1").is_signed())
4271 self.assertTrue(Decimal("0").is_zero())
4272 self.assertTrue(Decimal("0").is_zero())
4273
4274 # Copy
4275 with localcontext() as c:
4276 c.prec = 10000
4277 x = 1228 ** 1523
4278 y = -Decimal(x)
4279
4280 z = y.copy_abs()
4281 self.assertEqual(z, x)
4282
4283 z = y.copy_negate()
4284 self.assertEqual(z, x)
4285
4286 z = y.copy_sign(Decimal(1))
4287 self.assertEqual(z, x)
4288
4289 def test_divmod(self):
4290 Decimal = self.decimal.Decimal
4291 localcontext = self.decimal.localcontext
4292 InvalidOperation = self.decimal.InvalidOperation
4293 DivisionByZero = self.decimal.DivisionByZero
4294
4295 with localcontext() as c:
4296 q, r = divmod(Decimal("10912837129"), 1001)
4297 self.assertEqual(q, Decimal('10901935'))
4298 self.assertEqual(r, Decimal('194'))
4299
4300 q, r = divmod(Decimal("NaN"), 7)
4301 self.assertTrue(q.is_nan() and r.is_nan())
4302
4303 c.traps[InvalidOperation] = False
4304 q, r = divmod(Decimal("NaN"), 7)
4305 self.assertTrue(q.is_nan() and r.is_nan())
4306
4307 c.traps[InvalidOperation] = False
4308 c.clear_flags()
4309 q, r = divmod(Decimal("inf"), Decimal("inf"))
4310 self.assertTrue(q.is_nan() and r.is_nan())
4311 self.assertTrue(c.flags[InvalidOperation])
4312
4313 c.clear_flags()
4314 q, r = divmod(Decimal("inf"), 101)
4315 self.assertTrue(q.is_infinite() and r.is_nan())
4316 self.assertTrue(c.flags[InvalidOperation])
4317
4318 c.clear_flags()
4319 q, r = divmod(Decimal(0), 0)
4320 self.assertTrue(q.is_nan() and r.is_nan())
4321 self.assertTrue(c.flags[InvalidOperation])
4322
4323 c.traps[DivisionByZero] = False
4324 c.clear_flags()
4325 q, r = divmod(Decimal(11), 0)
4326 self.assertTrue(q.is_infinite() and r.is_nan())
4327 self.assertTrue(c.flags[InvalidOperation] and
4328 c.flags[DivisionByZero])
4329
4330 def test_power(self):
4331 Decimal = self.decimal.Decimal
4332 localcontext = self.decimal.localcontext
4333 Overflow = self.decimal.Overflow
4334 Rounded = self.decimal.Rounded
4335
4336 with localcontext() as c:
4337 c.prec = 3
4338 c.clear_flags()
4339 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4340 self.assertTrue(c.flags[Rounded])
4341
4342 c.prec = 1
4343 c.Emax = 1
4344 c.Emin = -1
4345 c.clear_flags()
4346 c.traps[Overflow] = False
4347 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4348 self.assertTrue(c.flags[Overflow])
4349
4350 def test_quantize(self):
4351 Decimal = self.decimal.Decimal
4352 localcontext = self.decimal.localcontext
4353 InvalidOperation = self.decimal.InvalidOperation
4354
4355 with localcontext() as c:
4356 c.prec = 1
4357 c.Emax = 1
4358 c.Emin = -1
4359 c.traps[InvalidOperation] = False
4360 x = Decimal(99).quantize(Decimal("1e1"))
4361 self.assertTrue(x.is_nan())
4362
4363 def test_radix(self):
4364 Decimal = self.decimal.Decimal
4365 getcontext = self.decimal.getcontext
4366
4367 c = getcontext()
4368 self.assertEqual(Decimal("1").radix(), 10)
4369 self.assertEqual(c.radix(), 10)
4370
4371 def test_rop(self):
4372 Decimal = self.decimal.Decimal
4373
4374 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4375 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4376 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4377
4378 def test_round(self):
4379 # Python3 behavior: round() returns Decimal
4380 Decimal = self.decimal.Decimal
4381 getcontext = self.decimal.getcontext
4382
4383 c = getcontext()
4384 c.prec = 28
4385
4386 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4387 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4388 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4389 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4390 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4391
4392 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4393 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4394
4395 def test_create_decimal(self):
4396 c = self.decimal.Context()
4397 self.assertRaises(ValueError, c.create_decimal, ["%"])
4398
4399 def test_int(self):
4400 Decimal = self.decimal.Decimal
4401 localcontext = self.decimal.localcontext
4402
4403 with localcontext() as c:
4404 c.prec = 9999
4405 x = Decimal(1221**1271) / 10**3923
4406 self.assertEqual(int(x), 1)
4407 self.assertEqual(x.to_integral(), 2)
4408
4409 def test_copy(self):
4410 Context = self.decimal.Context
4411
4412 c = Context()
4413 c.prec = 10000
4414 x = -(1172 ** 1712)
4415
4416 y = c.copy_abs(x)
4417 self.assertEqual(y, -x)
4418
4419 y = c.copy_negate(x)
4420 self.assertEqual(y, -x)
4421
4422 y = c.copy_sign(x, 1)
4423 self.assertEqual(y, -x)
4424
4425class CCoverage(Coverage):
4426 decimal = C
4427class PyCoverage(Coverage):
4428 decimal = P
4429
4430class PyFunctionality(unittest.TestCase):
4431 """Extra functionality in decimal.py"""
4432
4433 def test_py_quantize_watchexp(self):
4434 # watchexp functionality
4435 Decimal = P.Decimal
4436 localcontext = P.localcontext
4437
4438 with localcontext() as c:
4439 c.prec = 1
4440 c.Emax = 1
4441 c.Emin = -1
4442 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4443 self.assertEqual(x, Decimal('1.00E+5'))
4444
4445 def test_py_alternate_formatting(self):
4446 # triples giving a format, a Decimal, and the expected result
4447 Decimal = P.Decimal
4448 localcontext = P.localcontext
4449
4450 test_values = [
4451 # Issue 7094: Alternate formatting (specified by #)
4452 ('.0e', '1.0', '1e+0'),
4453 ('#.0e', '1.0', '1.e+0'),
4454 ('.0f', '1.0', '1'),
4455 ('#.0f', '1.0', '1.'),
4456 ('g', '1.1', '1.1'),
4457 ('#g', '1.1', '1.1'),
4458 ('.0g', '1', '1'),
4459 ('#.0g', '1', '1.'),
4460 ('.0%', '1.0', '100%'),
4461 ('#.0%', '1.0', '100.%'),
4462 ]
4463 for fmt, d, result in test_values:
4464 self.assertEqual(format(Decimal(d), fmt), result)
4465
4466class PyWhitebox(unittest.TestCase):
4467 """White box testing for decimal.py"""
4468
4469 def test_py_exact_power(self):
4470 # Rarely exercised lines in _power_exact.
4471 Decimal = P.Decimal
4472 localcontext = P.localcontext
4473
4474 with localcontext() as c:
4475 c.prec = 8
4476 x = Decimal(2**16) ** Decimal("-0.5")
4477 self.assertEqual(x, Decimal('0.00390625'))
4478
4479 x = Decimal(2**16) ** Decimal("-0.6")
4480 self.assertEqual(x, Decimal('0.0012885819'))
4481
4482 x = Decimal("256e7") ** Decimal("-0.5")
4483
4484 x = Decimal(152587890625) ** Decimal('-0.0625')
4485 self.assertEqual(x, Decimal("0.2"))
4486
4487 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4488
4489 x = Decimal(5**2659) ** Decimal('-0.0625')
4490
4491 c.prec = 1
4492 x = Decimal("152587890625") ** Decimal('-0.5')
4493 c.prec = 201
4494 x = Decimal(2**578) ** Decimal("-0.5")
4495
4496 def test_py_immutability_operations(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004497 # Do operations and check that it didn't change change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004498 Decimal = P.Decimal
4499 DefaultContext = P.DefaultContext
4500 setcontext = P.setcontext
4501
4502 c = DefaultContext.copy()
4503 c.traps = dict((s, 0) for s in OrderedSignals[P])
4504 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004505
4506 d1 = Decimal('-25e55')
4507 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004508 d2 = Decimal('33e+33')
4509 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004510
4511 def checkSameDec(operation, useOther=False):
4512 if useOther:
4513 eval("d1." + operation + "(d2)")
4514 self.assertEqual(d1._sign, b1._sign)
4515 self.assertEqual(d1._int, b1._int)
4516 self.assertEqual(d1._exp, b1._exp)
4517 self.assertEqual(d2._sign, b2._sign)
4518 self.assertEqual(d2._int, b2._int)
4519 self.assertEqual(d2._exp, b2._exp)
4520 else:
4521 eval("d1." + operation + "()")
4522 self.assertEqual(d1._sign, b1._sign)
4523 self.assertEqual(d1._int, b1._int)
4524 self.assertEqual(d1._exp, b1._exp)
4525 return
4526
4527 Decimal(d1)
4528 self.assertEqual(d1._sign, b1._sign)
4529 self.assertEqual(d1._int, b1._int)
4530 self.assertEqual(d1._exp, b1._exp)
4531
4532 checkSameDec("__abs__")
4533 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004534 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004535 checkSameDec("__eq__", True)
4536 checkSameDec("__ne__", True)
4537 checkSameDec("__le__", True)
4538 checkSameDec("__lt__", True)
4539 checkSameDec("__ge__", True)
4540 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004541 checkSameDec("__float__")
4542 checkSameDec("__floordiv__", True)
4543 checkSameDec("__hash__")
4544 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004545 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004546 checkSameDec("__mod__", True)
4547 checkSameDec("__mul__", True)
4548 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004549 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004550 checkSameDec("__pos__")
4551 checkSameDec("__pow__", True)
4552 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004553 checkSameDec("__rdivmod__", True)
4554 checkSameDec("__repr__")
4555 checkSameDec("__rfloordiv__", True)
4556 checkSameDec("__rmod__", True)
4557 checkSameDec("__rmul__", True)
4558 checkSameDec("__rpow__", True)
4559 checkSameDec("__rsub__", True)
4560 checkSameDec("__str__")
4561 checkSameDec("__sub__", True)
4562 checkSameDec("__truediv__", True)
4563 checkSameDec("adjusted")
4564 checkSameDec("as_tuple")
4565 checkSameDec("compare", True)
4566 checkSameDec("max", True)
4567 checkSameDec("min", True)
4568 checkSameDec("normalize")
4569 checkSameDec("quantize", True)
4570 checkSameDec("remainder_near", True)
4571 checkSameDec("same_quantum", True)
4572 checkSameDec("sqrt")
4573 checkSameDec("to_eng_string")
4574 checkSameDec("to_integral")
4575
Stefan Krah1919b7e2012-03-21 18:25:23 +01004576 def test_py_decimal_id(self):
4577 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004578
Stefan Krah1919b7e2012-03-21 18:25:23 +01004579 d = Decimal(45)
4580 e = Decimal(d)
4581 self.assertEqual(str(e), '45')
4582 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004583
Stefan Krah1919b7e2012-03-21 18:25:23 +01004584 def test_py_rescale(self):
4585 # Coverage
4586 Decimal = P.Decimal
4587 ROUND_UP = P.ROUND_UP
4588 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004589
Stefan Krah1919b7e2012-03-21 18:25:23 +01004590 with localcontext() as c:
4591 x = Decimal("NaN")._rescale(3, ROUND_UP)
4592 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004593
Stefan Krah1919b7e2012-03-21 18:25:23 +01004594 def test_py__round(self):
4595 # Coverage
4596 Decimal = P.Decimal
4597 ROUND_UP = P.ROUND_UP
Christian Heimes0348fb62008-03-26 12:55:56 +00004598
Stefan Krah1919b7e2012-03-21 18:25:23 +01004599 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004600
Stefan Krah1919b7e2012-03-21 18:25:23 +01004601class CFunctionality(unittest.TestCase):
4602 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004603
Stefan Krah1919b7e2012-03-21 18:25:23 +01004604 @requires_extra_functionality
4605 def test_c_ieee_context(self):
4606 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4607 IEEEContext = C.IEEEContext
4608 DECIMAL32 = C.DECIMAL32
4609 DECIMAL64 = C.DECIMAL64
4610 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004611
Stefan Krah1919b7e2012-03-21 18:25:23 +01004612 def assert_rest(self, context):
4613 self.assertEqual(context.clamp, 1)
4614 assert_signals(self, context, 'traps', [])
4615 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004616
Stefan Krah1919b7e2012-03-21 18:25:23 +01004617 c = IEEEContext(DECIMAL32)
4618 self.assertEqual(c.prec, 7)
4619 self.assertEqual(c.Emax, 96)
4620 self.assertEqual(c.Emin, -95)
4621 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004622
Stefan Krah1919b7e2012-03-21 18:25:23 +01004623 c = IEEEContext(DECIMAL64)
4624 self.assertEqual(c.prec, 16)
4625 self.assertEqual(c.Emax, 384)
4626 self.assertEqual(c.Emin, -383)
4627 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004628
Stefan Krah1919b7e2012-03-21 18:25:23 +01004629 c = IEEEContext(DECIMAL128)
4630 self.assertEqual(c.prec, 34)
4631 self.assertEqual(c.Emax, 6144)
4632 self.assertEqual(c.Emin, -6143)
4633 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004634
Stefan Krah1919b7e2012-03-21 18:25:23 +01004635 # Invalid values
4636 self.assertRaises(OverflowError, IEEEContext, 2**63)
4637 self.assertRaises(ValueError, IEEEContext, -1)
4638 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004639
Stefan Krah1919b7e2012-03-21 18:25:23 +01004640 @requires_extra_functionality
4641 def test_c_context(self):
4642 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004643
Stefan Krah1919b7e2012-03-21 18:25:23 +01004644 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4645 self.assertEqual(c._flags, C.DecClamped)
4646 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004647
Stefan Krah1919b7e2012-03-21 18:25:23 +01004648 @requires_extra_functionality
4649 def test_constants(self):
4650 # Condition flags
4651 cond = (
4652 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4653 C.DecDivisionImpossible, C.DecDivisionUndefined,
4654 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4655 C.DecInvalidOperation, C.DecMallocError,
4656 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4657 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004658 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004659
4660 # IEEEContext
4661 self.assertEqual(C.DECIMAL32, 32)
4662 self.assertEqual(C.DECIMAL64, 64)
4663 self.assertEqual(C.DECIMAL128, 128)
4664 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4665
4666 # Rounding modes
4667 for i, v in enumerate(RoundingModes[C]):
4668 self.assertEqual(v, i)
4669 self.assertEqual(C.ROUND_TRUNC, 8)
4670
4671 # Conditions
4672 for i, v in enumerate(cond):
4673 self.assertEqual(v, 1<<i)
4674
4675 self.assertEqual(C.DecIEEEInvalidOperation,
4676 C.DecConversionSyntax|
4677 C.DecDivisionImpossible|
4678 C.DecDivisionUndefined|
4679 C.DecFpuError|
4680 C.DecInvalidContext|
4681 C.DecInvalidOperation|
4682 C.DecMallocError)
4683
4684 self.assertEqual(C.DecErrors,
4685 C.DecIEEEInvalidOperation|
4686 C.DecDivisionByZero)
4687
4688 self.assertEqual(C.DecTraps,
4689 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4690
4691class CWhitebox(unittest.TestCase):
4692 """Whitebox testing for _decimal"""
4693
4694 def test_bignum(self):
4695 # Not exactly whitebox, but too slow with pydecimal.
4696
4697 Decimal = C.Decimal
4698 localcontext = C.localcontext
4699
4700 b1 = 10**35
4701 b2 = 10**36
4702 with localcontext() as c:
4703 c.prec = 1000000
4704 for i in range(5):
4705 a = random.randrange(b1, b2)
4706 b = random.randrange(1000, 1200)
4707 x = a ** b
4708 y = Decimal(a) ** Decimal(b)
4709 self.assertEqual(x, y)
4710
4711 def test_invalid_construction(self):
4712 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4713
4714 def test_c_input_restriction(self):
4715 # Too large for _decimal to be converted exactly
4716 Decimal = C.Decimal
4717 InvalidOperation = C.InvalidOperation
4718 Context = C.Context
4719 localcontext = C.localcontext
4720
4721 with localcontext(Context()):
4722 self.assertRaises(InvalidOperation, Decimal,
4723 "1e9999999999999999999")
4724
4725 def test_c_context_repr(self):
4726 # This test is _decimal-only because flags are not printed
4727 # in the same order.
4728 DefaultContext = C.DefaultContext
4729 FloatOperation = C.FloatOperation
4730 ROUND_HALF_DOWN = C.ROUND_HALF_DOWN
4731
4732 c = DefaultContext.copy()
4733
4734 c.prec = 425000000
4735 c.Emax = 425000000
4736 c.Emin = -425000000
4737 c.rounding = ROUND_HALF_DOWN
4738 c.capitals = 0
4739 c.clamp = 1
4740 for sig in OrderedSignals[C]:
4741 c.flags[sig] = True
4742 c.traps[sig] = True
4743 c.flags[FloatOperation] = True
4744 c.traps[FloatOperation] = True
4745
4746 s = c.__repr__()
4747 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4748 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4749 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4750 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4751 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4752 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4753 self.assertEqual(s, t)
4754
4755 def test_c_context_errors(self):
4756 Context = C.Context
4757 InvalidOperation = C.InvalidOperation
4758 Overflow = C.Overflow
4759 FloatOperation = C.FloatOperation
4760 localcontext = C.localcontext
4761 getcontext = C.getcontext
4762 setcontext = C.setcontext
4763 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4764
4765 c = Context()
4766
4767 # SignalDict: input validation
4768 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4769 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4770 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4771 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4772 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4773 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4774 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4775 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4776
4777 # Test assignment from a signal dict with the correct length but
4778 # one invalid key.
4779 d = c.flags.copy()
4780 del d[FloatOperation]
4781 d["XYZ"] = 91283719
4782 self.assertRaises(KeyError, setattr, c, 'flags', d)
4783 self.assertRaises(KeyError, setattr, c, 'traps', d)
4784
4785 # Input corner cases
4786 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4787 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4788
4789 # prec, Emax, Emin
4790 for attr in ['prec', 'Emax']:
4791 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4792 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4793
4794 # prec, Emax, Emin in context constructor
4795 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4796 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4797 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4798
4799 # Overflow in conversion
4800 self.assertRaises(OverflowError, Context, prec=int_max+1)
4801 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4802 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
4803 self.assertRaises(OverflowError, Context, rounding=int_max+1)
4804 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4805 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4806
4807 # OverflowError, general ValueError
4808 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4809 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4810 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4811 if sys.platform != 'win32':
4812 self.assertRaises(ValueError, setattr, c, attr, int_max)
4813 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4814
4815 # OverflowError, general TypeError
4816 for attr in ('rounding',):
4817 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4818 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4819 if sys.platform != 'win32':
4820 self.assertRaises(TypeError, setattr, c, attr, int_max)
4821 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4822
4823 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4824 if C.MAX_PREC == 425000000:
4825 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4826 int_max+1)
4827 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4828 int_max+1)
4829 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4830 -int_max-2)
4831
4832 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4833 if C.MAX_PREC == 425000000:
4834 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4835 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4836 1070000001)
4837 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4838 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4839 1070000001)
4840 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4841 -1070000001)
4842 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4843
4844 # capitals, clamp
4845 for attr in ['capitals', 'clamp']:
4846 self.assertRaises(ValueError, setattr, c, attr, -1)
4847 self.assertRaises(ValueError, setattr, c, attr, 2)
4848 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4849 if HAVE_CONFIG_64:
4850 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4851 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4852
4853 # Invalid local context
4854 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4855 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004856 self.assertRaises(TypeError, exec,
4857 'with localcontext(context=getcontext()): pass',
4858 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004859
4860 # setcontext
4861 saved_context = getcontext()
4862 self.assertRaises(TypeError, setcontext, "xyz")
4863 setcontext(saved_context)
4864
4865 @requires_extra_functionality
4866 def test_c_context_errors_extra(self):
4867 Context = C.Context
4868 InvalidOperation = C.InvalidOperation
4869 Overflow = C.Overflow
4870 localcontext = C.localcontext
4871 getcontext = C.getcontext
4872 setcontext = C.setcontext
4873 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4874
4875 c = Context()
4876
4877 # Input corner cases
4878 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4879
4880 # OverflowError, general ValueError
4881 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4882 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4883 if sys.platform != 'win32':
4884 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4885 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4886
4887 # OverflowError, general TypeError
4888 for attr in ('_flags', '_traps'):
4889 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4890 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4891 if sys.platform != 'win32':
4892 self.assertRaises(TypeError, setattr, c, attr, int_max)
4893 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4894
4895 # _allcr
4896 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4897 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4898 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4899 if HAVE_CONFIG_64:
4900 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4901 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4902
4903 # _flags, _traps
4904 for attr in ['_flags', '_traps']:
4905 self.assertRaises(TypeError, setattr, c, attr, 999999)
4906 self.assertRaises(TypeError, setattr, c, attr, 'x')
4907
4908 def test_c_valid_context(self):
4909 # These tests are for code coverage in _decimal.
4910 DefaultContext = C.DefaultContext
4911 ROUND_HALF_UP = C.ROUND_HALF_UP
4912 Clamped = C.Clamped
4913 Underflow = C.Underflow
4914 Inexact = C.Inexact
4915 Rounded = C.Rounded
4916 Subnormal = C.Subnormal
4917
4918 c = DefaultContext.copy()
4919
4920 # Exercise all getters and setters
4921 c.prec = 34
4922 c.rounding = ROUND_HALF_UP
4923 c.Emax = 3000
4924 c.Emin = -3000
4925 c.capitals = 1
4926 c.clamp = 0
4927
4928 self.assertEqual(c.prec, 34)
4929 self.assertEqual(c.rounding, ROUND_HALF_UP)
4930 self.assertEqual(c.Emin, -3000)
4931 self.assertEqual(c.Emax, 3000)
4932 self.assertEqual(c.capitals, 1)
4933 self.assertEqual(c.clamp, 0)
4934
4935 self.assertEqual(c.Etiny(), -3033)
4936 self.assertEqual(c.Etop(), 2967)
4937
4938 # Exercise all unsafe setters
4939 if C.MAX_PREC == 425000000:
4940 c._unsafe_setprec(999999999)
4941 c._unsafe_setemax(999999999)
4942 c._unsafe_setemin(-999999999)
4943 self.assertEqual(c.prec, 999999999)
4944 self.assertEqual(c.Emax, 999999999)
4945 self.assertEqual(c.Emin, -999999999)
4946
4947 @requires_extra_functionality
4948 def test_c_valid_context_extra(self):
4949 DefaultContext = C.DefaultContext
4950
4951 c = DefaultContext.copy()
4952 self.assertEqual(c._allcr, 1)
4953 c._allcr = 0
4954 self.assertEqual(c._allcr, 0)
4955
4956 def test_c_round(self):
4957 # Restricted input.
4958 Decimal = C.Decimal
4959 InvalidOperation = C.InvalidOperation
4960 localcontext = C.localcontext
4961 MAX_EMAX = C.MAX_EMAX
4962 MIN_ETINY = C.MIN_ETINY
4963 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4964
4965 with localcontext() as c:
4966 c.traps[InvalidOperation] = True
4967 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4968 -int_max-1)
4969 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4970 int_max)
4971 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4972 int(MAX_EMAX+1))
4973 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4974 -int(MIN_ETINY-1))
4975 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4976 -int_max-2)
4977 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4978 int_max+1)
4979
4980 def test_c_format(self):
4981 # Restricted input
4982 Decimal = C.Decimal
4983 InvalidOperation = C.InvalidOperation
4984 Rounded = C.Rounded
4985 localcontext = C.localcontext
4986 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4987
4988 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4989 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4990 self.assertRaises(TypeError, Decimal(1).__format__, [])
4991
4992 with localcontext() as c:
4993 c.traps[InvalidOperation] = True
4994 c.traps[Rounded] = True
4995 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4996 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4997 self.assertRaises(InvalidOperation, Decimal("1.23456789").__format__,
4998 "=%d.1" % maxsize)
4999
5000 def test_c_integral(self):
5001 Decimal = C.Decimal
5002 Inexact = C.Inexact
5003 ROUND_UP = C.ROUND_UP
5004 localcontext = C.localcontext
5005
5006 x = Decimal(10)
5007 self.assertEqual(x.to_integral(), 10)
5008 self.assertRaises(TypeError, x.to_integral, '10')
5009 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5010 self.assertRaises(TypeError, x.to_integral, 10)
5011
5012 self.assertEqual(x.to_integral_value(), 10)
5013 self.assertRaises(TypeError, x.to_integral_value, '10')
5014 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5015 self.assertRaises(TypeError, x.to_integral_value, 10)
5016
5017 self.assertEqual(x.to_integral_exact(), 10)
5018 self.assertRaises(TypeError, x.to_integral_exact, '10')
5019 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5020 self.assertRaises(TypeError, x.to_integral_exact, 10)
5021
5022 with localcontext() as c:
5023 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5024 self.assertEqual(x, Decimal('100000000000000000000000000'))
5025
5026 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5027 self.assertEqual(x, Decimal('100000000000000000000000000'))
5028
5029 c.traps[Inexact] = True
5030 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5031
5032 def test_c_funcs(self):
5033 # Invalid arguments
5034 Decimal = C.Decimal
5035 InvalidOperation = C.InvalidOperation
5036 DivisionByZero = C.DivisionByZero
5037 ROUND_UP = C.ROUND_UP
5038 getcontext = C.getcontext
5039 localcontext = C.localcontext
5040
5041 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5042
5043 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5044 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5045 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5046
Raymond Hettinger771ed762009-01-03 19:20:32 +00005047 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005048 TypeError,
5049 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005050 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005051 self.assertRaises(
5052 TypeError,
5053 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5054 )
5055 self.assertRaises(
5056 TypeError,
5057 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5058 )
5059 self.assertRaises(
5060 TypeError,
5061 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5062 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005063
Stefan Krah1919b7e2012-03-21 18:25:23 +01005064 with localcontext() as c:
5065 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005066
Stefan Krah1919b7e2012-03-21 18:25:23 +01005067 # Invalid arguments
5068 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5069 self.assertRaises(TypeError, c.canonical, 200)
5070 self.assertRaises(TypeError, c.is_canonical, 200)
5071 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5072 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005073
Stefan Krah1919b7e2012-03-21 18:25:23 +01005074 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5075 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005076
Stefan Krah1919b7e2012-03-21 18:25:23 +01005077 c.traps[DivisionByZero] = True
5078 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5079 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5080 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005081
Stefan Krah1919b7e2012-03-21 18:25:23 +01005082 c.clear_flags()
5083 c.traps[InvalidOperation] = True
5084 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5085 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5086 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005087
Stefan Krah1919b7e2012-03-21 18:25:23 +01005088 c.traps[InvalidOperation] = True
5089 c.prec = 2
5090 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005091
Stefan Krah040e3112012-12-15 22:33:33 +01005092 def test_va_args_exceptions(self):
5093 Decimal = C.Decimal
5094 Context = C.Context
5095
5096 x = Decimal("10001111111")
5097
5098 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5099 'logb', 'logical_invert', 'next_minus', 'next_plus',
5100 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5101 func = getattr(x, attr)
5102 self.assertRaises(TypeError, func, context="x")
5103 self.assertRaises(TypeError, func, "x", context=None)
5104
5105 for attr in ['compare', 'compare_signal', 'logical_and',
5106 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5107 'remainder_near', 'rotate', 'scaleb', 'shift']:
5108 func = getattr(x, attr)
5109 self.assertRaises(TypeError, func, context="x")
5110 self.assertRaises(TypeError, func, "x", context=None)
5111
5112 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5113 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5114 self.assertRaises(TypeError, x.to_integral, [], [])
5115
5116 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5117 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5118 self.assertRaises(TypeError, x.to_integral_value, [], [])
5119
5120 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5121 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5122 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5123
5124 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5125 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5126
5127 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5128 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5129 self.assertRaises(TypeError, x.quantize, 1, [], [])
5130
5131 c = Context()
5132 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5133 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5134 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5135
Stefan Krah1919b7e2012-03-21 18:25:23 +01005136 @requires_extra_functionality
5137 def test_c_context_templates(self):
5138 self.assertEqual(
5139 C.BasicContext._traps,
5140 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5141 C.DecUnderflow|C.DecClamped
5142 )
5143 self.assertEqual(
5144 C.DefaultContext._traps,
5145 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5146 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005147
Stefan Krah1919b7e2012-03-21 18:25:23 +01005148 @requires_extra_functionality
5149 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005150
Stefan Krah1919b7e2012-03-21 18:25:23 +01005151 # SignalDict coverage
5152 Context = C.Context
5153 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005154
Stefan Krah1919b7e2012-03-21 18:25:23 +01005155 InvalidOperation = C.InvalidOperation
5156 DivisionByZero = C.DivisionByZero
5157 Overflow = C.Overflow
5158 Subnormal = C.Subnormal
5159 Underflow = C.Underflow
5160 Rounded = C.Rounded
5161 Inexact = C.Inexact
5162 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005163
Stefan Krah1919b7e2012-03-21 18:25:23 +01005164 DecClamped = C.DecClamped
5165 DecInvalidOperation = C.DecInvalidOperation
5166 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005167
Stefan Krah1919b7e2012-03-21 18:25:23 +01005168 def assertIsExclusivelySet(signal, signal_dict):
5169 for sig in signal_dict:
5170 if sig == signal:
5171 self.assertTrue(signal_dict[sig])
5172 else:
5173 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005174
Stefan Krah1919b7e2012-03-21 18:25:23 +01005175 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005176
Stefan Krah1919b7e2012-03-21 18:25:23 +01005177 # Signal dict methods
5178 self.assertTrue(Overflow in c.traps)
5179 c.clear_traps()
5180 for k in c.traps.keys():
5181 c.traps[k] = True
5182 for v in c.traps.values():
5183 self.assertTrue(v)
5184 c.clear_traps()
5185 for k, v in c.traps.items():
5186 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005187
Stefan Krah1919b7e2012-03-21 18:25:23 +01005188 self.assertFalse(c.flags.get(Overflow))
5189 self.assertIs(c.flags.get("x"), None)
5190 self.assertEqual(c.flags.get("x", "y"), "y")
5191 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005192
Stefan Krah1919b7e2012-03-21 18:25:23 +01005193 self.assertEqual(len(c.flags), len(c.traps))
5194 s = sys.getsizeof(c.flags)
5195 s = sys.getsizeof(c.traps)
5196 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005197
Stefan Krah1919b7e2012-03-21 18:25:23 +01005198 # Set flags/traps.
5199 c.clear_flags()
5200 c._flags = DecClamped
5201 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005202
Stefan Krah1919b7e2012-03-21 18:25:23 +01005203 c.clear_traps()
5204 c._traps = DecInvalidOperation
5205 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005206
Stefan Krah1919b7e2012-03-21 18:25:23 +01005207 # Set flags/traps from dictionary.
5208 c.clear_flags()
5209 d = c.flags.copy()
5210 d[DivisionByZero] = True
5211 c.flags = d
5212 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005213
Stefan Krah1919b7e2012-03-21 18:25:23 +01005214 c.clear_traps()
5215 d = c.traps.copy()
5216 d[Underflow] = True
5217 c.traps = d
5218 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005219
Stefan Krah1919b7e2012-03-21 18:25:23 +01005220 # Random constructors
5221 IntSignals = {
5222 Clamped: C.DecClamped,
5223 Rounded: C.DecRounded,
5224 Inexact: C.DecInexact,
5225 Subnormal: C.DecSubnormal,
5226 Underflow: C.DecUnderflow,
5227 Overflow: C.DecOverflow,
5228 DivisionByZero: C.DecDivisionByZero,
5229 InvalidOperation: C.DecIEEEInvalidOperation
5230 }
5231 IntCond = [
5232 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5233 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5234 C.DecConversionSyntax,
5235 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005236
Stefan Krah1919b7e2012-03-21 18:25:23 +01005237 lim = len(OrderedSignals[C])
5238 for r in range(lim):
5239 for t in range(lim):
5240 for round in RoundingModes[C]:
5241 flags = random.sample(OrderedSignals[C], r)
5242 traps = random.sample(OrderedSignals[C], t)
5243 prec = random.randrange(1, 10000)
5244 emin = random.randrange(-10000, 0)
5245 emax = random.randrange(0, 10000)
5246 clamp = random.randrange(0, 2)
5247 caps = random.randrange(0, 2)
5248 cr = random.randrange(0, 2)
5249 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5250 capitals=caps, clamp=clamp, flags=list(flags),
5251 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005252
Stefan Krah1919b7e2012-03-21 18:25:23 +01005253 self.assertEqual(c.prec, prec)
5254 self.assertEqual(c.rounding, round)
5255 self.assertEqual(c.Emin, emin)
5256 self.assertEqual(c.Emax, emax)
5257 self.assertEqual(c.capitals, caps)
5258 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005259
Stefan Krah1919b7e2012-03-21 18:25:23 +01005260 f = 0
5261 for x in flags:
5262 f |= IntSignals[x]
5263 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005264
Stefan Krah1919b7e2012-03-21 18:25:23 +01005265 f = 0
5266 for x in traps:
5267 f |= IntSignals[x]
5268 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005269
Stefan Krah1919b7e2012-03-21 18:25:23 +01005270 for cond in IntCond:
5271 c._flags = cond
5272 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5273 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005274
Stefan Krah1919b7e2012-03-21 18:25:23 +01005275 for cond in IntCond:
5276 c._traps = cond
5277 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5278 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005279
Stefan Krah1919b7e2012-03-21 18:25:23 +01005280 def test_invalid_override(self):
5281 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005282
Stefan Krah1919b7e2012-03-21 18:25:23 +01005283 try:
5284 from locale import CHAR_MAX
5285 except ImportError:
5286 return
Mark Dickinson84230a12010-02-18 14:49:50 +00005287
Stefan Krah1919b7e2012-03-21 18:25:23 +01005288 def make_grouping(lst):
5289 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005290
Stefan Krah1919b7e2012-03-21 18:25:23 +01005291 def get_fmt(x, override=None, fmt='n'):
5292 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005293
Stefan Krah1919b7e2012-03-21 18:25:23 +01005294 invalid_grouping = {
5295 'decimal_point' : ',',
5296 'grouping' : make_grouping([255, 255, 0]),
5297 'thousands_sep' : ','
5298 }
5299 invalid_dot = {
5300 'decimal_point' : 'xxxxx',
5301 'grouping' : make_grouping([3, 3, 0]),
5302 'thousands_sep' : ','
5303 }
5304 invalid_sep = {
5305 'decimal_point' : '.',
5306 'grouping' : make_grouping([3, 3, 0]),
5307 'thousands_sep' : 'yyyyy'
5308 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005309
Stefan Krah1919b7e2012-03-21 18:25:23 +01005310 if CHAR_MAX == 127: # negative grouping in override
5311 self.assertRaises(ValueError, get_fmt, 12345,
5312 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005313
Stefan Krah1919b7e2012-03-21 18:25:23 +01005314 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5315 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005316
Stefan Krah0774e9b2012-04-05 15:21:58 +02005317 def test_exact_conversion(self):
5318 Decimal = C.Decimal
5319 localcontext = C.localcontext
5320 InvalidOperation = C.InvalidOperation
5321
5322 with localcontext() as c:
5323
5324 c.traps[InvalidOperation] = True
5325
5326 # Clamped
5327 x = "0e%d" % sys.maxsize
5328 self.assertRaises(InvalidOperation, Decimal, x)
5329
5330 x = "0e%d" % (-sys.maxsize-1)
5331 self.assertRaises(InvalidOperation, Decimal, x)
5332
5333 # Overflow
5334 x = "1e%d" % sys.maxsize
5335 self.assertRaises(InvalidOperation, Decimal, x)
5336
5337 # Underflow
5338 x = "1e%d" % (-sys.maxsize-1)
5339 self.assertRaises(InvalidOperation, Decimal, x)
5340
Stefan Krahff3eca02012-04-05 15:46:19 +02005341 def test_from_tuple(self):
5342 Decimal = C.Decimal
5343 localcontext = C.localcontext
5344 InvalidOperation = C.InvalidOperation
5345 Overflow = C.Overflow
5346 Underflow = C.Underflow
5347
5348 with localcontext() as c:
5349
5350 c.traps[InvalidOperation] = True
5351 c.traps[Overflow] = True
5352 c.traps[Underflow] = True
5353
5354 # SSIZE_MAX
5355 x = (1, (), sys.maxsize)
5356 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5357 self.assertRaises(InvalidOperation, Decimal, x)
5358
5359 x = (1, (0, 1, 2), sys.maxsize)
5360 self.assertRaises(Overflow, c.create_decimal, x)
5361 self.assertRaises(InvalidOperation, Decimal, x)
5362
5363 # SSIZE_MIN
5364 x = (1, (), -sys.maxsize-1)
5365 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5366 self.assertRaises(InvalidOperation, Decimal, x)
5367
5368 x = (1, (0, 1, 2), -sys.maxsize-1)
5369 self.assertRaises(Underflow, c.create_decimal, x)
5370 self.assertRaises(InvalidOperation, Decimal, x)
5371
5372 # OverflowError
5373 x = (1, (), sys.maxsize+1)
5374 self.assertRaises(OverflowError, c.create_decimal, x)
5375 self.assertRaises(OverflowError, Decimal, x)
5376
5377 x = (1, (), -sys.maxsize-2)
5378 self.assertRaises(OverflowError, c.create_decimal, x)
5379 self.assertRaises(OverflowError, Decimal, x)
5380
5381 # Specials
5382 x = (1, (), "N")
5383 self.assertEqual(str(Decimal(x)), '-sNaN')
5384 x = (1, (0,), "N")
5385 self.assertEqual(str(Decimal(x)), '-sNaN')
5386 x = (1, (0, 1), "N")
5387 self.assertEqual(str(Decimal(x)), '-sNaN1')
5388
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005389
Stefan Krah1919b7e2012-03-21 18:25:23 +01005390all_tests = [
5391 CExplicitConstructionTest, PyExplicitConstructionTest,
5392 CImplicitConstructionTest, PyImplicitConstructionTest,
5393 CFormatTest, PyFormatTest,
5394 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5395 CThreadingTest, PyThreadingTest,
5396 CUsabilityTest, PyUsabilityTest,
5397 CPythonAPItests, PyPythonAPItests,
5398 CContextAPItests, PyContextAPItests,
5399 CContextWithStatement, PyContextWithStatement,
5400 CContextFlags, PyContextFlags,
5401 CSpecialContexts, PySpecialContexts,
5402 CContextInputValidation, PyContextInputValidation,
5403 CContextSubclassing, PyContextSubclassing,
5404 CCoverage, PyCoverage,
5405 CFunctionality, PyFunctionality,
5406 CWhitebox, PyWhitebox,
5407 CIBMTestCases, PyIBMTestCases,
5408]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005409
Stefan Krah1919b7e2012-03-21 18:25:23 +01005410# Delete C tests if _decimal.so is not present.
5411if not C:
5412 all_tests = all_tests[1::2]
5413else:
5414 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005415
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005416
5417def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005418 """ Execute the tests.
5419
Raymond Hettingered20ad82004-09-04 20:09:13 +00005420 Runs all arithmetic tests if arith is True or if the "decimal" resource
5421 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005422 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005423
Stefan Krah1919b7e2012-03-21 18:25:23 +01005424 init(C)
5425 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005426 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00005427 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005428 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005429
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005430 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005431 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005432 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005433 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005434
5435 # Dynamically build custom test definition for each file in the test
5436 # directory and add the definitions to the DecimalTest class. This
5437 # procedure insures that new files do not get skipped.
5438 for filename in os.listdir(directory):
5439 if '.decTest' not in filename or filename.startswith("."):
5440 continue
5441 head, tail = filename.split('.')
5442 if todo_tests is not None and head not in todo_tests:
5443 continue
5444 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005445 setattr(CIBMTestCases, 'test_' + head, tester)
5446 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005447 del filename, head, tail, tester
5448
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005449
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005450 try:
5451 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005452 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005453 from doctest import IGNORE_EXCEPTION_DETAIL
5454 savedecimal = sys.modules['decimal']
5455 if C:
5456 sys.modules['decimal'] = C
5457 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5458 sys.modules['decimal'] = P
5459 run_doctest(P, verbose)
5460 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005461 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005462 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5463 P.setcontext(ORIGINAL_CONTEXT[P])
5464 if not C:
5465 warnings.warn('C tests skipped: no module named _decimal.',
5466 UserWarning)
5467 if not orig_sys_decimal is sys.modules['decimal']:
5468 raise TestFailed("Internal error: unbalanced number of changes to "
5469 "sys.modules['decimal'].")
5470
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005471
5472if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005473 import optparse
5474 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5475 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5476 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5477 (opt, args) = p.parse_args()
5478
5479 if opt.skip:
5480 test_main(arith=False, verbose=True)
5481 elif args:
5482 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005483 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005484 test_main(arith=True, verbose=True)