blob: 0dddc4ba6bb5bd93f824db2ff7a05120032e9413 [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
2721 def test_pickle(self):
2722
2723 Context = self.decimal.Context
2724
2725 savedecimal = sys.modules['decimal']
2726
2727 # Round trip
2728 sys.modules['decimal'] = self.decimal
2729 c = Context()
2730 e = pickle.loads(pickle.dumps(c))
2731
2732 self.assertEqual(c.prec, e.prec)
2733 self.assertEqual(c.Emin, e.Emin)
2734 self.assertEqual(c.Emax, e.Emax)
2735 self.assertEqual(c.rounding, e.rounding)
2736 self.assertEqual(c.capitals, e.capitals)
2737 self.assertEqual(c.clamp, e.clamp)
2738 self.assertEqual(c.flags, e.flags)
2739 self.assertEqual(c.traps, e.traps)
2740
2741 # Test interchangeability
2742 combinations = [(C, P), (P, C)] if C else [(P, P)]
2743 for dumper, loader in combinations:
2744 for ri, _ in enumerate(RoundingModes[dumper]):
2745 for fi, _ in enumerate(OrderedSignals[dumper]):
2746 for ti, _ in enumerate(OrderedSignals[dumper]):
2747
2748 prec = random.randrange(1, 100)
2749 emin = random.randrange(-100, 0)
2750 emax = random.randrange(1, 100)
2751 caps = random.randrange(2)
2752 clamp = random.randrange(2)
2753
2754 # One module dumps
2755 sys.modules['decimal'] = dumper
2756 c = dumper.Context(
2757 prec=prec, Emin=emin, Emax=emax,
2758 rounding=RoundingModes[dumper][ri],
2759 capitals=caps, clamp=clamp,
2760 flags=OrderedSignals[dumper][:fi],
2761 traps=OrderedSignals[dumper][:ti]
2762 )
2763 s = pickle.dumps(c)
2764
2765 # The other module loads
2766 sys.modules['decimal'] = loader
2767 d = pickle.loads(s)
2768 self.assertIsInstance(d, loader.Context)
2769
2770 self.assertEqual(d.prec, prec)
2771 self.assertEqual(d.Emin, emin)
2772 self.assertEqual(d.Emax, emax)
2773 self.assertEqual(d.rounding, RoundingModes[loader][ri])
2774 self.assertEqual(d.capitals, caps)
2775 self.assertEqual(d.clamp, clamp)
2776 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2777 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2778
2779 sys.modules['decimal'] = savedecimal
2780
2781 def test_equality_with_other_types(self):
2782 Decimal = self.decimal.Decimal
2783
2784 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2785 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2786
2787 def test_copy(self):
2788 # All copies should be deep
2789 Decimal = self.decimal.Decimal
2790 Context = self.decimal.Context
2791
2792 c = Context()
2793 d = c.copy()
2794 self.assertNotEqual(id(c), id(d))
2795 self.assertNotEqual(id(c.flags), id(d.flags))
2796 self.assertNotEqual(id(c.traps), id(d.traps))
2797 k1 = set(c.flags.keys())
2798 k2 = set(d.flags.keys())
2799 self.assertEqual(k1, k2)
2800 self.assertEqual(c.flags, d.flags)
2801
2802 def test__clamp(self):
2803 # In Python 3.2, the private attribute `_clamp` was made
2804 # public (issue 8540), with the old `_clamp` becoming a
2805 # property wrapping `clamp`. For the duration of Python 3.2
2806 # only, the attribute should be gettable/settable via both
2807 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2808 # removed.
2809 Context = self.decimal.Context
2810 c = Context()
2811 self.assertRaises(AttributeError, getattr, c, '_clamp')
2812
2813 def test_abs(self):
2814 Decimal = self.decimal.Decimal
2815 Context = self.decimal.Context
2816
2817 c = Context()
2818 d = c.abs(Decimal(-1))
2819 self.assertEqual(c.abs(-1), d)
2820 self.assertRaises(TypeError, c.abs, '-1')
2821
2822 def test_add(self):
2823 Decimal = self.decimal.Decimal
2824 Context = self.decimal.Context
2825
2826 c = Context()
2827 d = c.add(Decimal(1), Decimal(1))
2828 self.assertEqual(c.add(1, 1), d)
2829 self.assertEqual(c.add(Decimal(1), 1), d)
2830 self.assertEqual(c.add(1, Decimal(1)), d)
2831 self.assertRaises(TypeError, c.add, '1', 1)
2832 self.assertRaises(TypeError, c.add, 1, '1')
2833
2834 def test_compare(self):
2835 Decimal = self.decimal.Decimal
2836 Context = self.decimal.Context
2837
2838 c = Context()
2839 d = c.compare(Decimal(1), Decimal(1))
2840 self.assertEqual(c.compare(1, 1), d)
2841 self.assertEqual(c.compare(Decimal(1), 1), d)
2842 self.assertEqual(c.compare(1, Decimal(1)), d)
2843 self.assertRaises(TypeError, c.compare, '1', 1)
2844 self.assertRaises(TypeError, c.compare, 1, '1')
2845
2846 def test_compare_signal(self):
2847 Decimal = self.decimal.Decimal
2848 Context = self.decimal.Context
2849
2850 c = Context()
2851 d = c.compare_signal(Decimal(1), Decimal(1))
2852 self.assertEqual(c.compare_signal(1, 1), d)
2853 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2854 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2855 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2856 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2857
2858 def test_compare_total(self):
2859 Decimal = self.decimal.Decimal
2860 Context = self.decimal.Context
2861
2862 c = Context()
2863 d = c.compare_total(Decimal(1), Decimal(1))
2864 self.assertEqual(c.compare_total(1, 1), d)
2865 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2866 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2867 self.assertRaises(TypeError, c.compare_total, '1', 1)
2868 self.assertRaises(TypeError, c.compare_total, 1, '1')
2869
2870 def test_compare_total_mag(self):
2871 Decimal = self.decimal.Decimal
2872 Context = self.decimal.Context
2873
2874 c = Context()
2875 d = c.compare_total_mag(Decimal(1), Decimal(1))
2876 self.assertEqual(c.compare_total_mag(1, 1), d)
2877 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2878 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2879 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2880 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2881
2882 def test_copy_abs(self):
2883 Decimal = self.decimal.Decimal
2884 Context = self.decimal.Context
2885
2886 c = Context()
2887 d = c.copy_abs(Decimal(-1))
2888 self.assertEqual(c.copy_abs(-1), d)
2889 self.assertRaises(TypeError, c.copy_abs, '-1')
2890
2891 def test_copy_decimal(self):
2892 Decimal = self.decimal.Decimal
2893 Context = self.decimal.Context
2894
2895 c = Context()
2896 d = c.copy_decimal(Decimal(-1))
2897 self.assertEqual(c.copy_decimal(-1), d)
2898 self.assertRaises(TypeError, c.copy_decimal, '-1')
2899
2900 def test_copy_negate(self):
2901 Decimal = self.decimal.Decimal
2902 Context = self.decimal.Context
2903
2904 c = Context()
2905 d = c.copy_negate(Decimal(-1))
2906 self.assertEqual(c.copy_negate(-1), d)
2907 self.assertRaises(TypeError, c.copy_negate, '-1')
2908
2909 def test_copy_sign(self):
2910 Decimal = self.decimal.Decimal
2911 Context = self.decimal.Context
2912
2913 c = Context()
2914 d = c.copy_sign(Decimal(1), Decimal(-2))
2915 self.assertEqual(c.copy_sign(1, -2), d)
2916 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2917 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2918 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2919 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2920
2921 def test_divide(self):
2922 Decimal = self.decimal.Decimal
2923 Context = self.decimal.Context
2924
2925 c = Context()
2926 d = c.divide(Decimal(1), Decimal(2))
2927 self.assertEqual(c.divide(1, 2), d)
2928 self.assertEqual(c.divide(Decimal(1), 2), d)
2929 self.assertEqual(c.divide(1, Decimal(2)), d)
2930 self.assertRaises(TypeError, c.divide, '1', 2)
2931 self.assertRaises(TypeError, c.divide, 1, '2')
2932
2933 def test_divide_int(self):
2934 Decimal = self.decimal.Decimal
2935 Context = self.decimal.Context
2936
2937 c = Context()
2938 d = c.divide_int(Decimal(1), Decimal(2))
2939 self.assertEqual(c.divide_int(1, 2), d)
2940 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2941 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2942 self.assertRaises(TypeError, c.divide_int, '1', 2)
2943 self.assertRaises(TypeError, c.divide_int, 1, '2')
2944
2945 def test_divmod(self):
2946 Decimal = self.decimal.Decimal
2947 Context = self.decimal.Context
2948
2949 c = Context()
2950 d = c.divmod(Decimal(1), Decimal(2))
2951 self.assertEqual(c.divmod(1, 2), d)
2952 self.assertEqual(c.divmod(Decimal(1), 2), d)
2953 self.assertEqual(c.divmod(1, Decimal(2)), d)
2954 self.assertRaises(TypeError, c.divmod, '1', 2)
2955 self.assertRaises(TypeError, c.divmod, 1, '2')
2956
2957 def test_exp(self):
2958 Decimal = self.decimal.Decimal
2959 Context = self.decimal.Context
2960
2961 c = Context()
2962 d = c.exp(Decimal(10))
2963 self.assertEqual(c.exp(10), d)
2964 self.assertRaises(TypeError, c.exp, '10')
2965
2966 def test_fma(self):
2967 Decimal = self.decimal.Decimal
2968 Context = self.decimal.Context
2969
2970 c = Context()
2971 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
2972 self.assertEqual(c.fma(2, 3, 4), d)
2973 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
2974 self.assertEqual(c.fma(2, Decimal(3), 4), d)
2975 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
2976 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
2977 self.assertRaises(TypeError, c.fma, '2', 3, 4)
2978 self.assertRaises(TypeError, c.fma, 2, '3', 4)
2979 self.assertRaises(TypeError, c.fma, 2, 3, '4')
2980
2981 # Issue 12079 for Context.fma ...
2982 self.assertRaises(TypeError, c.fma,
2983 Decimal('Infinity'), Decimal(0), "not a decimal")
2984 self.assertRaises(TypeError, c.fma,
2985 Decimal(1), Decimal('snan'), 1.222)
2986 # ... and for Decimal.fma.
2987 self.assertRaises(TypeError, Decimal('Infinity').fma,
2988 Decimal(0), "not a decimal")
2989 self.assertRaises(TypeError, Decimal(1).fma,
2990 Decimal('snan'), 1.222)
2991
2992 def test_is_finite(self):
2993 Decimal = self.decimal.Decimal
2994 Context = self.decimal.Context
2995
2996 c = Context()
2997 d = c.is_finite(Decimal(10))
2998 self.assertEqual(c.is_finite(10), d)
2999 self.assertRaises(TypeError, c.is_finite, '10')
3000
3001 def test_is_infinite(self):
3002 Decimal = self.decimal.Decimal
3003 Context = self.decimal.Context
3004
3005 c = Context()
3006 d = c.is_infinite(Decimal(10))
3007 self.assertEqual(c.is_infinite(10), d)
3008 self.assertRaises(TypeError, c.is_infinite, '10')
3009
3010 def test_is_nan(self):
3011 Decimal = self.decimal.Decimal
3012 Context = self.decimal.Context
3013
3014 c = Context()
3015 d = c.is_nan(Decimal(10))
3016 self.assertEqual(c.is_nan(10), d)
3017 self.assertRaises(TypeError, c.is_nan, '10')
3018
3019 def test_is_normal(self):
3020 Decimal = self.decimal.Decimal
3021 Context = self.decimal.Context
3022
3023 c = Context()
3024 d = c.is_normal(Decimal(10))
3025 self.assertEqual(c.is_normal(10), d)
3026 self.assertRaises(TypeError, c.is_normal, '10')
3027
3028 def test_is_qnan(self):
3029 Decimal = self.decimal.Decimal
3030 Context = self.decimal.Context
3031
3032 c = Context()
3033 d = c.is_qnan(Decimal(10))
3034 self.assertEqual(c.is_qnan(10), d)
3035 self.assertRaises(TypeError, c.is_qnan, '10')
3036
3037 def test_is_signed(self):
3038 Decimal = self.decimal.Decimal
3039 Context = self.decimal.Context
3040
3041 c = Context()
3042 d = c.is_signed(Decimal(10))
3043 self.assertEqual(c.is_signed(10), d)
3044 self.assertRaises(TypeError, c.is_signed, '10')
3045
3046 def test_is_snan(self):
3047 Decimal = self.decimal.Decimal
3048 Context = self.decimal.Context
3049
3050 c = Context()
3051 d = c.is_snan(Decimal(10))
3052 self.assertEqual(c.is_snan(10), d)
3053 self.assertRaises(TypeError, c.is_snan, '10')
3054
3055 def test_is_subnormal(self):
3056 Decimal = self.decimal.Decimal
3057 Context = self.decimal.Context
3058
3059 c = Context()
3060 d = c.is_subnormal(Decimal(10))
3061 self.assertEqual(c.is_subnormal(10), d)
3062 self.assertRaises(TypeError, c.is_subnormal, '10')
3063
3064 def test_is_zero(self):
3065 Decimal = self.decimal.Decimal
3066 Context = self.decimal.Context
3067
3068 c = Context()
3069 d = c.is_zero(Decimal(10))
3070 self.assertEqual(c.is_zero(10), d)
3071 self.assertRaises(TypeError, c.is_zero, '10')
3072
3073 def test_ln(self):
3074 Decimal = self.decimal.Decimal
3075 Context = self.decimal.Context
3076
3077 c = Context()
3078 d = c.ln(Decimal(10))
3079 self.assertEqual(c.ln(10), d)
3080 self.assertRaises(TypeError, c.ln, '10')
3081
3082 def test_log10(self):
3083 Decimal = self.decimal.Decimal
3084 Context = self.decimal.Context
3085
3086 c = Context()
3087 d = c.log10(Decimal(10))
3088 self.assertEqual(c.log10(10), d)
3089 self.assertRaises(TypeError, c.log10, '10')
3090
3091 def test_logb(self):
3092 Decimal = self.decimal.Decimal
3093 Context = self.decimal.Context
3094
3095 c = Context()
3096 d = c.logb(Decimal(10))
3097 self.assertEqual(c.logb(10), d)
3098 self.assertRaises(TypeError, c.logb, '10')
3099
3100 def test_logical_and(self):
3101 Decimal = self.decimal.Decimal
3102 Context = self.decimal.Context
3103
3104 c = Context()
3105 d = c.logical_and(Decimal(1), Decimal(1))
3106 self.assertEqual(c.logical_and(1, 1), d)
3107 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3108 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3109 self.assertRaises(TypeError, c.logical_and, '1', 1)
3110 self.assertRaises(TypeError, c.logical_and, 1, '1')
3111
3112 def test_logical_invert(self):
3113 Decimal = self.decimal.Decimal
3114 Context = self.decimal.Context
3115
3116 c = Context()
3117 d = c.logical_invert(Decimal(1000))
3118 self.assertEqual(c.logical_invert(1000), d)
3119 self.assertRaises(TypeError, c.logical_invert, '1000')
3120
3121 def test_logical_or(self):
3122 Decimal = self.decimal.Decimal
3123 Context = self.decimal.Context
3124
3125 c = Context()
3126 d = c.logical_or(Decimal(1), Decimal(1))
3127 self.assertEqual(c.logical_or(1, 1), d)
3128 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3129 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3130 self.assertRaises(TypeError, c.logical_or, '1', 1)
3131 self.assertRaises(TypeError, c.logical_or, 1, '1')
3132
3133 def test_logical_xor(self):
3134 Decimal = self.decimal.Decimal
3135 Context = self.decimal.Context
3136
3137 c = Context()
3138 d = c.logical_xor(Decimal(1), Decimal(1))
3139 self.assertEqual(c.logical_xor(1, 1), d)
3140 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3141 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3142 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3143 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3144
3145 def test_max(self):
3146 Decimal = self.decimal.Decimal
3147 Context = self.decimal.Context
3148
3149 c = Context()
3150 d = c.max(Decimal(1), Decimal(2))
3151 self.assertEqual(c.max(1, 2), d)
3152 self.assertEqual(c.max(Decimal(1), 2), d)
3153 self.assertEqual(c.max(1, Decimal(2)), d)
3154 self.assertRaises(TypeError, c.max, '1', 2)
3155 self.assertRaises(TypeError, c.max, 1, '2')
3156
3157 def test_max_mag(self):
3158 Decimal = self.decimal.Decimal
3159 Context = self.decimal.Context
3160
3161 c = Context()
3162 d = c.max_mag(Decimal(1), Decimal(2))
3163 self.assertEqual(c.max_mag(1, 2), d)
3164 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3165 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3166 self.assertRaises(TypeError, c.max_mag, '1', 2)
3167 self.assertRaises(TypeError, c.max_mag, 1, '2')
3168
3169 def test_min(self):
3170 Decimal = self.decimal.Decimal
3171 Context = self.decimal.Context
3172
3173 c = Context()
3174 d = c.min(Decimal(1), Decimal(2))
3175 self.assertEqual(c.min(1, 2), d)
3176 self.assertEqual(c.min(Decimal(1), 2), d)
3177 self.assertEqual(c.min(1, Decimal(2)), d)
3178 self.assertRaises(TypeError, c.min, '1', 2)
3179 self.assertRaises(TypeError, c.min, 1, '2')
3180
3181 def test_min_mag(self):
3182 Decimal = self.decimal.Decimal
3183 Context = self.decimal.Context
3184
3185 c = Context()
3186 d = c.min_mag(Decimal(1), Decimal(2))
3187 self.assertEqual(c.min_mag(1, 2), d)
3188 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3189 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3190 self.assertRaises(TypeError, c.min_mag, '1', 2)
3191 self.assertRaises(TypeError, c.min_mag, 1, '2')
3192
3193 def test_minus(self):
3194 Decimal = self.decimal.Decimal
3195 Context = self.decimal.Context
3196
3197 c = Context()
3198 d = c.minus(Decimal(10))
3199 self.assertEqual(c.minus(10), d)
3200 self.assertRaises(TypeError, c.minus, '10')
3201
3202 def test_multiply(self):
3203 Decimal = self.decimal.Decimal
3204 Context = self.decimal.Context
3205
3206 c = Context()
3207 d = c.multiply(Decimal(1), Decimal(2))
3208 self.assertEqual(c.multiply(1, 2), d)
3209 self.assertEqual(c.multiply(Decimal(1), 2), d)
3210 self.assertEqual(c.multiply(1, Decimal(2)), d)
3211 self.assertRaises(TypeError, c.multiply, '1', 2)
3212 self.assertRaises(TypeError, c.multiply, 1, '2')
3213
3214 def test_next_minus(self):
3215 Decimal = self.decimal.Decimal
3216 Context = self.decimal.Context
3217
3218 c = Context()
3219 d = c.next_minus(Decimal(10))
3220 self.assertEqual(c.next_minus(10), d)
3221 self.assertRaises(TypeError, c.next_minus, '10')
3222
3223 def test_next_plus(self):
3224 Decimal = self.decimal.Decimal
3225 Context = self.decimal.Context
3226
3227 c = Context()
3228 d = c.next_plus(Decimal(10))
3229 self.assertEqual(c.next_plus(10), d)
3230 self.assertRaises(TypeError, c.next_plus, '10')
3231
3232 def test_next_toward(self):
3233 Decimal = self.decimal.Decimal
3234 Context = self.decimal.Context
3235
3236 c = Context()
3237 d = c.next_toward(Decimal(1), Decimal(2))
3238 self.assertEqual(c.next_toward(1, 2), d)
3239 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3240 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3241 self.assertRaises(TypeError, c.next_toward, '1', 2)
3242 self.assertRaises(TypeError, c.next_toward, 1, '2')
3243
3244 def test_normalize(self):
3245 Decimal = self.decimal.Decimal
3246 Context = self.decimal.Context
3247
3248 c = Context()
3249 d = c.normalize(Decimal(10))
3250 self.assertEqual(c.normalize(10), d)
3251 self.assertRaises(TypeError, c.normalize, '10')
3252
3253 def test_number_class(self):
3254 Decimal = self.decimal.Decimal
3255 Context = self.decimal.Context
3256
3257 c = Context()
3258 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3259 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3260 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3261
3262 def test_plus(self):
3263 Decimal = self.decimal.Decimal
3264 Context = self.decimal.Context
3265
3266 c = Context()
3267 d = c.plus(Decimal(10))
3268 self.assertEqual(c.plus(10), d)
3269 self.assertRaises(TypeError, c.plus, '10')
3270
3271 def test_power(self):
3272 Decimal = self.decimal.Decimal
3273 Context = self.decimal.Context
3274
3275 c = Context()
3276 d = c.power(Decimal(1), Decimal(4))
3277 self.assertEqual(c.power(1, 4), d)
3278 self.assertEqual(c.power(Decimal(1), 4), d)
3279 self.assertEqual(c.power(1, Decimal(4)), d)
3280 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3281 self.assertRaises(TypeError, c.power, '1', 4)
3282 self.assertRaises(TypeError, c.power, 1, '4')
3283 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3284
3285 def test_quantize(self):
3286 Decimal = self.decimal.Decimal
3287 Context = self.decimal.Context
3288
3289 c = Context()
3290 d = c.quantize(Decimal(1), Decimal(2))
3291 self.assertEqual(c.quantize(1, 2), d)
3292 self.assertEqual(c.quantize(Decimal(1), 2), d)
3293 self.assertEqual(c.quantize(1, Decimal(2)), d)
3294 self.assertRaises(TypeError, c.quantize, '1', 2)
3295 self.assertRaises(TypeError, c.quantize, 1, '2')
3296
3297 def test_remainder(self):
3298 Decimal = self.decimal.Decimal
3299 Context = self.decimal.Context
3300
3301 c = Context()
3302 d = c.remainder(Decimal(1), Decimal(2))
3303 self.assertEqual(c.remainder(1, 2), d)
3304 self.assertEqual(c.remainder(Decimal(1), 2), d)
3305 self.assertEqual(c.remainder(1, Decimal(2)), d)
3306 self.assertRaises(TypeError, c.remainder, '1', 2)
3307 self.assertRaises(TypeError, c.remainder, 1, '2')
3308
3309 def test_remainder_near(self):
3310 Decimal = self.decimal.Decimal
3311 Context = self.decimal.Context
3312
3313 c = Context()
3314 d = c.remainder_near(Decimal(1), Decimal(2))
3315 self.assertEqual(c.remainder_near(1, 2), d)
3316 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3317 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3318 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3319 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3320
3321 def test_rotate(self):
3322 Decimal = self.decimal.Decimal
3323 Context = self.decimal.Context
3324
3325 c = Context()
3326 d = c.rotate(Decimal(1), Decimal(2))
3327 self.assertEqual(c.rotate(1, 2), d)
3328 self.assertEqual(c.rotate(Decimal(1), 2), d)
3329 self.assertEqual(c.rotate(1, Decimal(2)), d)
3330 self.assertRaises(TypeError, c.rotate, '1', 2)
3331 self.assertRaises(TypeError, c.rotate, 1, '2')
3332
3333 def test_sqrt(self):
3334 Decimal = self.decimal.Decimal
3335 Context = self.decimal.Context
3336
3337 c = Context()
3338 d = c.sqrt(Decimal(10))
3339 self.assertEqual(c.sqrt(10), d)
3340 self.assertRaises(TypeError, c.sqrt, '10')
3341
3342 def test_same_quantum(self):
3343 Decimal = self.decimal.Decimal
3344 Context = self.decimal.Context
3345
3346 c = Context()
3347 d = c.same_quantum(Decimal(1), Decimal(2))
3348 self.assertEqual(c.same_quantum(1, 2), d)
3349 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3350 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3351 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3352 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3353
3354 def test_scaleb(self):
3355 Decimal = self.decimal.Decimal
3356 Context = self.decimal.Context
3357
3358 c = Context()
3359 d = c.scaleb(Decimal(1), Decimal(2))
3360 self.assertEqual(c.scaleb(1, 2), d)
3361 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3362 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3363 self.assertRaises(TypeError, c.scaleb, '1', 2)
3364 self.assertRaises(TypeError, c.scaleb, 1, '2')
3365
3366 def test_shift(self):
3367 Decimal = self.decimal.Decimal
3368 Context = self.decimal.Context
3369
3370 c = Context()
3371 d = c.shift(Decimal(1), Decimal(2))
3372 self.assertEqual(c.shift(1, 2), d)
3373 self.assertEqual(c.shift(Decimal(1), 2), d)
3374 self.assertEqual(c.shift(1, Decimal(2)), d)
3375 self.assertRaises(TypeError, c.shift, '1', 2)
3376 self.assertRaises(TypeError, c.shift, 1, '2')
3377
3378 def test_subtract(self):
3379 Decimal = self.decimal.Decimal
3380 Context = self.decimal.Context
3381
3382 c = Context()
3383 d = c.subtract(Decimal(1), Decimal(2))
3384 self.assertEqual(c.subtract(1, 2), d)
3385 self.assertEqual(c.subtract(Decimal(1), 2), d)
3386 self.assertEqual(c.subtract(1, Decimal(2)), d)
3387 self.assertRaises(TypeError, c.subtract, '1', 2)
3388 self.assertRaises(TypeError, c.subtract, 1, '2')
3389
3390 def test_to_eng_string(self):
3391 Decimal = self.decimal.Decimal
3392 Context = self.decimal.Context
3393
3394 c = Context()
3395 d = c.to_eng_string(Decimal(10))
3396 self.assertEqual(c.to_eng_string(10), d)
3397 self.assertRaises(TypeError, c.to_eng_string, '10')
3398
3399 def test_to_sci_string(self):
3400 Decimal = self.decimal.Decimal
3401 Context = self.decimal.Context
3402
3403 c = Context()
3404 d = c.to_sci_string(Decimal(10))
3405 self.assertEqual(c.to_sci_string(10), d)
3406 self.assertRaises(TypeError, c.to_sci_string, '10')
3407
3408 def test_to_integral_exact(self):
3409 Decimal = self.decimal.Decimal
3410 Context = self.decimal.Context
3411
3412 c = Context()
3413 d = c.to_integral_exact(Decimal(10))
3414 self.assertEqual(c.to_integral_exact(10), d)
3415 self.assertRaises(TypeError, c.to_integral_exact, '10')
3416
3417 def test_to_integral_value(self):
3418 Decimal = self.decimal.Decimal
3419 Context = self.decimal.Context
3420
3421 c = Context()
3422 d = c.to_integral_value(Decimal(10))
3423 self.assertEqual(c.to_integral_value(10), d)
3424 self.assertRaises(TypeError, c.to_integral_value, '10')
3425 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3426
3427class CContextAPItests(ContextAPItests):
3428 decimal = C
3429class PyContextAPItests(ContextAPItests):
3430 decimal = P
3431
3432class ContextWithStatement(unittest.TestCase):
3433 # Can't do these as docstrings until Python 2.6
3434 # as doctest can't handle __future__ statements
3435
3436 def test_localcontext(self):
3437 # Use a copy of the current context in the block
3438 getcontext = self.decimal.getcontext
3439 localcontext = self.decimal.localcontext
3440
3441 orig_ctx = getcontext()
3442 with localcontext() as enter_ctx:
3443 set_ctx = getcontext()
3444 final_ctx = getcontext()
3445 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3446 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3447 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3448
3449 def test_localcontextarg(self):
3450 # Use a copy of the supplied context in the block
3451 Context = self.decimal.Context
3452 getcontext = self.decimal.getcontext
3453 localcontext = self.decimal.localcontext
3454
3455 localcontext = self.decimal.localcontext
3456 orig_ctx = getcontext()
3457 new_ctx = Context(prec=42)
3458 with localcontext(new_ctx) as enter_ctx:
3459 set_ctx = getcontext()
3460 final_ctx = getcontext()
3461 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3462 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3463 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3464 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3465
3466 def test_nested_with_statements(self):
3467 # Use a copy of the supplied context in the block
3468 Decimal = self.decimal.Decimal
3469 Context = self.decimal.Context
3470 getcontext = self.decimal.getcontext
3471 localcontext = self.decimal.localcontext
3472 Clamped = self.decimal.Clamped
3473 Overflow = self.decimal.Overflow
3474
3475 orig_ctx = getcontext()
3476 orig_ctx.clear_flags()
3477 new_ctx = Context(Emax=384)
3478 with localcontext() as c1:
3479 self.assertEqual(c1.flags, orig_ctx.flags)
3480 self.assertEqual(c1.traps, orig_ctx.traps)
3481 c1.traps[Clamped] = True
3482 c1.Emin = -383
3483 self.assertNotEqual(orig_ctx.Emin, -383)
3484 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3485 self.assertTrue(c1.flags[Clamped])
3486 with localcontext(new_ctx) as c2:
3487 self.assertEqual(c2.flags, new_ctx.flags)
3488 self.assertEqual(c2.traps, new_ctx.traps)
3489 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3490 self.assertFalse(c2.flags[Clamped])
3491 self.assertTrue(c2.flags[Overflow])
3492 del c2
3493 self.assertFalse(c1.flags[Overflow])
3494 del c1
3495 self.assertNotEqual(orig_ctx.Emin, -383)
3496 self.assertFalse(orig_ctx.flags[Clamped])
3497 self.assertFalse(orig_ctx.flags[Overflow])
3498 self.assertFalse(new_ctx.flags[Clamped])
3499 self.assertFalse(new_ctx.flags[Overflow])
3500
3501 def test_with_statements_gc1(self):
3502 localcontext = self.decimal.localcontext
3503
3504 with localcontext() as c1:
3505 del c1
3506 with localcontext() as c2:
3507 del c2
3508 with localcontext() as c3:
3509 del c3
3510 with localcontext() as c4:
3511 del c4
3512
3513 def test_with_statements_gc2(self):
3514 localcontext = self.decimal.localcontext
3515
3516 with localcontext() as c1:
3517 with localcontext(c1) as c2:
3518 del c1
3519 with localcontext(c2) as c3:
3520 del c2
3521 with localcontext(c3) as c4:
3522 del c3
3523 del c4
3524
3525 def test_with_statements_gc3(self):
3526 Context = self.decimal.Context
3527 localcontext = self.decimal.localcontext
3528 getcontext = self.decimal.getcontext
3529 setcontext = self.decimal.setcontext
3530
3531 with localcontext() as c1:
3532 del c1
3533 n1 = Context(prec=1)
3534 setcontext(n1)
3535 with localcontext(n1) as c2:
3536 del n1
3537 self.assertEqual(c2.prec, 1)
3538 del c2
3539 n2 = Context(prec=2)
3540 setcontext(n2)
3541 del n2
3542 self.assertEqual(getcontext().prec, 2)
3543 n3 = Context(prec=3)
3544 setcontext(n3)
3545 self.assertEqual(getcontext().prec, 3)
3546 with localcontext(n3) as c3:
3547 del n3
3548 self.assertEqual(c3.prec, 3)
3549 del c3
3550 n4 = Context(prec=4)
3551 setcontext(n4)
3552 del n4
3553 self.assertEqual(getcontext().prec, 4)
3554 with localcontext() as c4:
3555 self.assertEqual(c4.prec, 4)
3556 del c4
3557
3558class CContextWithStatement(ContextWithStatement):
3559 decimal = C
3560class PyContextWithStatement(ContextWithStatement):
3561 decimal = P
3562
3563class ContextFlags(unittest.TestCase):
3564
3565 def test_flags_irrelevant(self):
3566 # check that the result (numeric result + flags raised) of an
3567 # arithmetic operation doesn't depend on the current flags
3568 Decimal = self.decimal.Decimal
3569 Context = self.decimal.Context
3570 Inexact = self.decimal.Inexact
3571 Rounded = self.decimal.Rounded
3572 Underflow = self.decimal.Underflow
3573 Clamped = self.decimal.Clamped
3574 Subnormal = self.decimal.Subnormal
3575 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
3576
3577 def raise_error(context, flag):
3578 if self.decimal == C:
3579 context.flags[flag] = True
3580 if context.traps[flag]:
3581 raise flag
3582 else:
3583 context._raise_error(flag)
3584
3585 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3586 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3587
3588 # operations that raise various flags, in the form (function, arglist)
3589 operations = [
3590 (context._apply, [Decimal("100E-425000010")]),
3591 (context.sqrt, [Decimal(2)]),
3592 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3593 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3594 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3595 ]
3596
3597 # try various flags individually, then a whole lot at once
3598 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3599 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3600
3601 for fn, args in operations:
3602 # find answer and flags raised using a clean context
3603 context.clear_flags()
3604 ans = fn(*args)
3605 flags = [k for k, v in context.flags.items() if v]
3606
3607 for extra_flags in flagsets:
3608 # set flags, before calling operation
3609 context.clear_flags()
3610 for flag in extra_flags:
3611 raise_error(context, flag)
3612 new_ans = fn(*args)
3613
3614 # flags that we expect to be set after the operation
3615 expected_flags = list(flags)
3616 for flag in extra_flags:
3617 if flag not in expected_flags:
3618 expected_flags.append(flag)
3619 expected_flags.sort(key=id)
3620
3621 # flags we actually got
3622 new_flags = [k for k,v in context.flags.items() if v]
3623 new_flags.sort(key=id)
3624
3625 self.assertEqual(ans, new_ans,
3626 "operation produces different answers depending on flags set: " +
3627 "expected %s, got %s." % (ans, new_ans))
3628 self.assertEqual(new_flags, expected_flags,
3629 "operation raises different flags depending on flags set: " +
3630 "expected %s, got %s" % (expected_flags, new_flags))
3631
3632 def test_flag_comparisons(self):
3633 Context = self.decimal.Context
3634 Inexact = self.decimal.Inexact
3635 Rounded = self.decimal.Rounded
3636
3637 c = Context()
3638
3639 # Valid SignalDict
3640 self.assertNotEqual(c.flags, c.traps)
3641 self.assertNotEqual(c.traps, c.flags)
3642
3643 c.flags = c.traps
3644 self.assertEqual(c.flags, c.traps)
3645 self.assertEqual(c.traps, c.flags)
3646
3647 c.flags[Rounded] = True
3648 c.traps = c.flags
3649 self.assertEqual(c.flags, c.traps)
3650 self.assertEqual(c.traps, c.flags)
3651
3652 d = {}
3653 d.update(c.flags)
3654 self.assertEqual(d, c.flags)
3655 self.assertEqual(c.flags, d)
3656
3657 d[Inexact] = True
3658 self.assertNotEqual(d, c.flags)
3659 self.assertNotEqual(c.flags, d)
3660
3661 # Invalid SignalDict
3662 d = {Inexact:False}
3663 self.assertNotEqual(d, c.flags)
3664 self.assertNotEqual(c.flags, d)
3665
3666 d = ["xyz"]
3667 self.assertNotEqual(d, c.flags)
3668 self.assertNotEqual(c.flags, d)
3669
3670 @requires_IEEE_754
3671 def test_float_operation(self):
3672 Decimal = self.decimal.Decimal
3673 FloatOperation = self.decimal.FloatOperation
3674 localcontext = self.decimal.localcontext
3675
3676 with localcontext() as c:
3677 ##### trap is off by default
3678 self.assertFalse(c.traps[FloatOperation])
3679
3680 # implicit conversion sets the flag
3681 c.clear_flags()
3682 self.assertEqual(Decimal(7.5), 7.5)
3683 self.assertTrue(c.flags[FloatOperation])
3684
3685 c.clear_flags()
3686 self.assertEqual(c.create_decimal(7.5), 7.5)
3687 self.assertTrue(c.flags[FloatOperation])
3688
3689 # explicit conversion does not set the flag
3690 c.clear_flags()
3691 x = Decimal.from_float(7.5)
3692 self.assertFalse(c.flags[FloatOperation])
3693 # comparison sets the flag
3694 self.assertEqual(x, 7.5)
3695 self.assertTrue(c.flags[FloatOperation])
3696
3697 c.clear_flags()
3698 x = c.create_decimal_from_float(7.5)
3699 self.assertFalse(c.flags[FloatOperation])
3700 self.assertEqual(x, 7.5)
3701 self.assertTrue(c.flags[FloatOperation])
3702
3703 ##### set the trap
3704 c.traps[FloatOperation] = True
3705
3706 # implicit conversion raises
3707 c.clear_flags()
3708 self.assertRaises(FloatOperation, Decimal, 7.5)
3709 self.assertTrue(c.flags[FloatOperation])
3710
3711 c.clear_flags()
3712 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3713 self.assertTrue(c.flags[FloatOperation])
3714
3715 # explicit conversion is silent
3716 c.clear_flags()
3717 x = Decimal.from_float(7.5)
3718 self.assertFalse(c.flags[FloatOperation])
3719
3720 c.clear_flags()
3721 x = c.create_decimal_from_float(7.5)
3722 self.assertFalse(c.flags[FloatOperation])
3723
3724 def test_float_comparison(self):
3725 Decimal = self.decimal.Decimal
3726 Context = self.decimal.Context
3727 FloatOperation = self.decimal.FloatOperation
3728 localcontext = self.decimal.localcontext
3729
3730 def assert_attr(a, b, attr, context, signal=None):
3731 context.clear_flags()
3732 f = getattr(a, attr)
3733 if signal == FloatOperation:
3734 self.assertRaises(signal, f, b)
3735 else:
3736 self.assertIs(f(b), True)
3737 self.assertTrue(context.flags[FloatOperation])
3738
3739 small_d = Decimal('0.25')
3740 big_d = Decimal('3.0')
3741 small_f = 0.25
3742 big_f = 3.0
3743
3744 zero_d = Decimal('0.0')
3745 neg_zero_d = Decimal('-0.0')
3746 zero_f = 0.0
3747 neg_zero_f = -0.0
3748
3749 inf_d = Decimal('Infinity')
3750 neg_inf_d = Decimal('-Infinity')
3751 inf_f = float('inf')
3752 neg_inf_f = float('-inf')
3753
3754 def doit(c, signal=None):
3755 # Order
3756 for attr in '__lt__', '__le__':
3757 assert_attr(small_d, big_f, attr, c, signal)
3758
3759 for attr in '__gt__', '__ge__':
3760 assert_attr(big_d, small_f, attr, c, signal)
3761
3762 # Equality
3763 assert_attr(small_d, small_f, '__eq__', c, None)
3764
3765 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3766 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3767
3768 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3769 assert_attr(zero_d, zero_f, '__eq__', c, None)
3770
3771 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3772 assert_attr(inf_d, inf_f, '__eq__', c, None)
3773
3774 # Inequality
3775 assert_attr(small_d, big_f, '__ne__', c, None)
3776
3777 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3778
3779 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3780 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3781
3782 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3783
3784 def test_containers(c, signal=None):
3785 c.clear_flags()
3786 s = set([100.0, Decimal('100.0')])
3787 self.assertEqual(len(s), 1)
3788 self.assertTrue(c.flags[FloatOperation])
3789
3790 c.clear_flags()
3791 if signal:
3792 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3793 else:
3794 s = sorted([10.0, Decimal('10.0')])
3795 self.assertTrue(c.flags[FloatOperation])
3796
3797 c.clear_flags()
3798 b = 10.0 in [Decimal('10.0'), 1.0]
3799 self.assertTrue(c.flags[FloatOperation])
3800
3801 c.clear_flags()
3802 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3803 self.assertTrue(c.flags[FloatOperation])
3804
3805 nc = Context()
3806 with localcontext(nc) as c:
3807 self.assertFalse(c.traps[FloatOperation])
3808 doit(c, signal=None)
3809 test_containers(c, signal=None)
3810
3811 c.traps[FloatOperation] = True
3812 doit(c, signal=FloatOperation)
3813 test_containers(c, signal=FloatOperation)
3814
3815 def test_float_operation_default(self):
3816 Decimal = self.decimal.Decimal
3817 Context = self.decimal.Context
3818 Inexact = self.decimal.Inexact
3819 FloatOperation= self.decimal.FloatOperation
3820
3821 context = Context()
3822 self.assertFalse(context.flags[FloatOperation])
3823 self.assertFalse(context.traps[FloatOperation])
3824
3825 context.clear_traps()
3826 context.traps[Inexact] = True
3827 context.traps[FloatOperation] = True
3828 self.assertTrue(context.traps[FloatOperation])
3829 self.assertTrue(context.traps[Inexact])
3830
3831class CContextFlags(ContextFlags):
3832 decimal = C
3833class PyContextFlags(ContextFlags):
3834 decimal = P
3835
3836class SpecialContexts(unittest.TestCase):
3837 """Test the context templates."""
3838
3839 def test_context_templates(self):
3840 BasicContext = self.decimal.BasicContext
3841 ExtendedContext = self.decimal.ExtendedContext
3842 getcontext = self.decimal.getcontext
3843 setcontext = self.decimal.setcontext
3844 InvalidOperation = self.decimal.InvalidOperation
3845 DivisionByZero = self.decimal.DivisionByZero
3846 Overflow = self.decimal.Overflow
3847 Underflow = self.decimal.Underflow
3848 Clamped = self.decimal.Clamped
3849
3850 assert_signals(self, BasicContext, 'traps',
3851 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3852 )
3853
3854 savecontext = getcontext().copy()
3855 basic_context_prec = BasicContext.prec
3856 extended_context_prec = ExtendedContext.prec
3857
3858 ex = None
3859 try:
3860 BasicContext.prec = ExtendedContext.prec = 441
3861 for template in BasicContext, ExtendedContext:
3862 setcontext(template)
3863 c = getcontext()
3864 self.assertIsNot(c, template)
3865 self.assertEqual(c.prec, 441)
3866 except Exception as e:
3867 ex = e.__class__
3868 finally:
3869 BasicContext.prec = basic_context_prec
3870 ExtendedContext.prec = extended_context_prec
3871 setcontext(savecontext)
3872 if ex:
3873 raise ex
3874
3875 def test_default_context(self):
3876 DefaultContext = self.decimal.DefaultContext
3877 BasicContext = self.decimal.BasicContext
3878 ExtendedContext = self.decimal.ExtendedContext
3879 getcontext = self.decimal.getcontext
3880 setcontext = self.decimal.setcontext
3881 InvalidOperation = self.decimal.InvalidOperation
3882 DivisionByZero = self.decimal.DivisionByZero
3883 Overflow = self.decimal.Overflow
3884
3885 self.assertEqual(BasicContext.prec, 9)
3886 self.assertEqual(ExtendedContext.prec, 9)
3887
3888 assert_signals(self, DefaultContext, 'traps',
3889 [InvalidOperation, DivisionByZero, Overflow]
3890 )
3891
3892 savecontext = getcontext().copy()
3893 default_context_prec = DefaultContext.prec
3894
3895 ex = None
3896 try:
3897 c = getcontext()
3898 saveprec = c.prec
3899
3900 DefaultContext.prec = 961
3901 c = getcontext()
3902 self.assertEqual(c.prec, saveprec)
3903
3904 setcontext(DefaultContext)
3905 c = getcontext()
3906 self.assertIsNot(c, DefaultContext)
3907 self.assertEqual(c.prec, 961)
3908 except Exception as e:
3909 ex = e.__class__
3910 finally:
3911 DefaultContext.prec = default_context_prec
3912 setcontext(savecontext)
3913 if ex:
3914 raise ex
3915
3916class CSpecialContexts(SpecialContexts):
3917 decimal = C
3918class PySpecialContexts(SpecialContexts):
3919 decimal = P
3920
3921class ContextInputValidation(unittest.TestCase):
3922
3923 def test_invalid_context(self):
3924 Context = self.decimal.Context
3925 DefaultContext = self.decimal.DefaultContext
3926
3927 c = DefaultContext.copy()
3928
3929 # prec, Emax
3930 for attr in ['prec', 'Emax']:
3931 setattr(c, attr, 999999)
3932 self.assertEqual(getattr(c, attr), 999999)
3933 self.assertRaises(ValueError, setattr, c, attr, -1)
3934 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3935
3936 # Emin
3937 setattr(c, 'Emin', -999999)
3938 self.assertEqual(getattr(c, 'Emin'), -999999)
3939 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3940 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3941
3942 # rounding: always raise TypeError in order to get consistent
3943 # exceptions across implementations. In decimal, rounding
3944 # modes are strings, in _decimal they are integers. The idea
3945 # is to view rounding as an abstract type and not mind the
3946 # implementation details.
3947 # Hence, a user should view the rounding modes as if they
3948 # had been defined in a language that supports abstract
3949 # data types, e.g. ocaml:
3950 #
3951 # type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;;
3952 #
3953 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3954 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3955 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3956 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3957
3958 # capitals, clamp
3959 for attr in ['capitals', 'clamp']:
3960 self.assertRaises(ValueError, setattr, c, attr, -1)
3961 self.assertRaises(ValueError, setattr, c, attr, 2)
3962 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3963
3964 # Invalid attribute
3965 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3966
3967 # Invalid signal dict
3968 self.assertRaises(TypeError, setattr, c, 'flags', [])
3969 self.assertRaises(KeyError, setattr, c, 'flags', {})
3970 self.assertRaises(KeyError, setattr, c, 'traps',
3971 {'InvalidOperation':0})
3972
3973 # Attributes cannot be deleted
3974 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3975 'flags', 'traps']:
3976 self.assertRaises(AttributeError, c.__delattr__, attr)
3977
3978 # Invalid attributes
3979 self.assertRaises(TypeError, getattr, c, 9)
3980 self.assertRaises(TypeError, setattr, c, 9)
3981
3982 # Invalid values in constructor
3983 self.assertRaises(TypeError, Context, rounding=999999)
3984 self.assertRaises(TypeError, Context, rounding='xyz')
3985 self.assertRaises(ValueError, Context, clamp=2)
3986 self.assertRaises(ValueError, Context, capitals=-1)
3987 self.assertRaises(KeyError, Context, flags=["P"])
3988 self.assertRaises(KeyError, Context, traps=["Q"])
3989
3990 # Type error in conversion
3991 self.assertRaises(TypeError, Context, flags=(0,1))
3992 self.assertRaises(TypeError, Context, traps=(1,0))
3993
3994class CContextInputValidation(ContextInputValidation):
3995 decimal = C
3996class PyContextInputValidation(ContextInputValidation):
3997 decimal = P
3998
3999class ContextSubclassing(unittest.TestCase):
4000
4001 def test_context_subclassing(self):
4002 decimal = self.decimal
4003 Decimal = decimal.Decimal
4004 Context = decimal.Context
4005 ROUND_HALF_EVEN = decimal.ROUND_HALF_EVEN
4006 ROUND_DOWN = decimal.ROUND_DOWN
4007 Clamped = decimal.Clamped
4008 DivisionByZero = decimal.DivisionByZero
4009 Inexact = decimal.Inexact
4010 Overflow = decimal.Overflow
4011 Rounded = decimal.Rounded
4012 Subnormal = decimal.Subnormal
4013 Underflow = decimal.Underflow
4014 InvalidOperation = decimal.InvalidOperation
4015
4016 class MyContext(Context):
4017 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4018 capitals=None, clamp=None, flags=None,
4019 traps=None):
4020 Context.__init__(self)
4021 if prec is not None:
4022 self.prec = prec
4023 if rounding is not None:
4024 self.rounding = rounding
4025 if Emin is not None:
4026 self.Emin = Emin
4027 if Emax is not None:
4028 self.Emax = Emax
4029 if capitals is not None:
4030 self.capitals = capitals
4031 if clamp is not None:
4032 self.clamp = clamp
4033 if flags is not None:
4034 if isinstance(flags, list):
4035 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4036 self.flags = flags
4037 if traps is not None:
4038 if isinstance(traps, list):
4039 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4040 self.traps = traps
4041
4042 c = Context()
4043 d = MyContext()
4044 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4045 'flags', 'traps'):
4046 self.assertEqual(getattr(c, attr), getattr(d, attr))
4047
4048 # prec
4049 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4050 c = MyContext(prec=1)
4051 self.assertEqual(c.prec, 1)
4052 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4053
4054 # rounding
4055 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4056 c = MyContext(rounding=ROUND_DOWN, prec=1)
4057 self.assertEqual(c.rounding, ROUND_DOWN)
4058 self.assertEqual(c.plus(Decimal('9.9')), 9)
4059
4060 # Emin
4061 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4062 c = MyContext(Emin=-1, prec=1)
4063 self.assertEqual(c.Emin, -1)
4064 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4065 self.assertEqual(x, Decimal('0.0'))
4066 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4067 self.assertTrue(c.flags[signal])
4068
4069 # Emax
4070 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4071 c = MyContext(Emax=1, prec=1)
4072 self.assertEqual(c.Emax, 1)
4073 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4074 if self.decimal == C:
4075 for signal in (Inexact, Overflow, Rounded):
4076 self.assertTrue(c.flags[signal])
4077
4078 # capitals
4079 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4080 c = MyContext(capitals=0)
4081 self.assertEqual(c.capitals, 0)
4082 x = c.create_decimal('1E222')
4083 self.assertEqual(c.to_sci_string(x), '1e+222')
4084
4085 # clamp
4086 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4087 c = MyContext(clamp=1, Emax=99)
4088 self.assertEqual(c.clamp, 1)
4089 x = c.plus(Decimal('1e99'))
4090 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4091
4092 # flags
4093 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4094 c = MyContext(flags=[Rounded, DivisionByZero])
4095 for signal in (Rounded, DivisionByZero):
4096 self.assertTrue(c.flags[signal])
4097 c.clear_flags()
4098 for signal in OrderedSignals[decimal]:
4099 self.assertFalse(c.flags[signal])
4100
4101 # traps
4102 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4103 c = MyContext(traps=[Rounded, DivisionByZero])
4104 for signal in (Rounded, DivisionByZero):
4105 self.assertTrue(c.traps[signal])
4106 c.clear_traps()
4107 for signal in OrderedSignals[decimal]:
4108 self.assertFalse(c.traps[signal])
4109
4110class CContextSubclassing(ContextSubclassing):
4111 decimal = C
4112class PyContextSubclassing(ContextSubclassing):
4113 decimal = P
4114
4115@skip_if_extra_functionality
4116class CheckAttributes(unittest.TestCase):
4117
4118 def test_module_attributes(self):
4119
4120 # Architecture dependent context limits
4121 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4122 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4123 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4124 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4125
4126 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4127 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4128
4129 self.assertEqual(C.__version__, P.__version__)
4130
4131 x = dir(C)
4132 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02004133 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004134
4135 def test_context_attributes(self):
4136
4137 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4138 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4139 self.assertEqual(set(x) - set(y), set())
4140
4141 def test_decimal_attributes(self):
4142
4143 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4144 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4145 self.assertEqual(set(x) - set(y), set())
4146
4147class Coverage(unittest.TestCase):
4148
4149 def test_adjusted(self):
4150 Decimal = self.decimal.Decimal
4151
4152 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4153 # XXX raise?
4154 self.assertEqual(Decimal('nan').adjusted(), 0)
4155 self.assertEqual(Decimal('inf').adjusted(), 0)
4156
4157 def test_canonical(self):
4158 Decimal = self.decimal.Decimal
4159 getcontext = self.decimal.getcontext
4160
4161 x = Decimal(9).canonical()
4162 self.assertEqual(x, 9)
4163
4164 c = getcontext()
4165 x = c.canonical(Decimal(9))
4166 self.assertEqual(x, 9)
4167
4168 def test_context_repr(self):
4169 c = self.decimal.DefaultContext.copy()
4170
4171 c.prec = 425000000
4172 c.Emax = 425000000
4173 c.Emin = -425000000
4174 c.rounding = self.decimal.ROUND_HALF_DOWN
4175 c.capitals = 0
4176 c.clamp = 1
4177 for sig in OrderedSignals[self.decimal]:
4178 c.flags[sig] = False
4179 c.traps[sig] = False
4180
4181 s = c.__repr__()
4182 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4183 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4184 "flags=[], traps=[])"
4185 self.assertEqual(s, t)
4186
4187 def test_implicit_context(self):
4188 Decimal = self.decimal.Decimal
4189 localcontext = self.decimal.localcontext
4190
4191 with localcontext() as c:
4192 c.prec = 1
4193 c.Emax = 1
4194 c.Emin = -1
4195
4196 # abs
4197 self.assertEqual(abs(Decimal("-10")), 10)
4198 # add
4199 self.assertEqual(Decimal("7") + 1, 8)
4200 # divide
4201 self.assertEqual(Decimal("10") / 5, 2)
4202 # divide_int
4203 self.assertEqual(Decimal("10") // 7, 1)
4204 # fma
4205 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4206 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4207 # three arg power
4208 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4209 # exp
4210 self.assertEqual(Decimal("1.01").exp(), 3)
4211 # is_normal
4212 self.assertIs(Decimal("0.01").is_normal(), False)
4213 # is_subnormal
4214 self.assertIs(Decimal("0.01").is_subnormal(), True)
4215 # ln
4216 self.assertEqual(Decimal("20").ln(), 3)
4217 # log10
4218 self.assertEqual(Decimal("20").log10(), 1)
4219 # logb
4220 self.assertEqual(Decimal("580").logb(), 2)
4221 # logical_invert
4222 self.assertEqual(Decimal("10").logical_invert(), 1)
4223 # minus
4224 self.assertEqual(-Decimal("-10"), 10)
4225 # multiply
4226 self.assertEqual(Decimal("2") * 4, 8)
4227 # next_minus
4228 self.assertEqual(Decimal("10").next_minus(), 9)
4229 # next_plus
4230 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4231 # normalize
4232 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4233 # number_class
4234 self.assertEqual(Decimal("10").number_class(), '+Normal')
4235 # plus
4236 self.assertEqual(+Decimal("-1"), -1)
4237 # remainder
4238 self.assertEqual(Decimal("10") % 7, 3)
4239 # subtract
4240 self.assertEqual(Decimal("10") - 7, 3)
4241 # to_integral_exact
4242 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4243
4244 # Boolean functions
4245 self.assertTrue(Decimal("1").is_canonical())
4246 self.assertTrue(Decimal("1").is_finite())
4247 self.assertTrue(Decimal("1").is_finite())
4248 self.assertTrue(Decimal("snan").is_snan())
4249 self.assertTrue(Decimal("-1").is_signed())
4250 self.assertTrue(Decimal("0").is_zero())
4251 self.assertTrue(Decimal("0").is_zero())
4252
4253 # Copy
4254 with localcontext() as c:
4255 c.prec = 10000
4256 x = 1228 ** 1523
4257 y = -Decimal(x)
4258
4259 z = y.copy_abs()
4260 self.assertEqual(z, x)
4261
4262 z = y.copy_negate()
4263 self.assertEqual(z, x)
4264
4265 z = y.copy_sign(Decimal(1))
4266 self.assertEqual(z, x)
4267
4268 def test_divmod(self):
4269 Decimal = self.decimal.Decimal
4270 localcontext = self.decimal.localcontext
4271 InvalidOperation = self.decimal.InvalidOperation
4272 DivisionByZero = self.decimal.DivisionByZero
4273
4274 with localcontext() as c:
4275 q, r = divmod(Decimal("10912837129"), 1001)
4276 self.assertEqual(q, Decimal('10901935'))
4277 self.assertEqual(r, Decimal('194'))
4278
4279 q, r = divmod(Decimal("NaN"), 7)
4280 self.assertTrue(q.is_nan() and r.is_nan())
4281
4282 c.traps[InvalidOperation] = False
4283 q, r = divmod(Decimal("NaN"), 7)
4284 self.assertTrue(q.is_nan() and r.is_nan())
4285
4286 c.traps[InvalidOperation] = False
4287 c.clear_flags()
4288 q, r = divmod(Decimal("inf"), Decimal("inf"))
4289 self.assertTrue(q.is_nan() and r.is_nan())
4290 self.assertTrue(c.flags[InvalidOperation])
4291
4292 c.clear_flags()
4293 q, r = divmod(Decimal("inf"), 101)
4294 self.assertTrue(q.is_infinite() and r.is_nan())
4295 self.assertTrue(c.flags[InvalidOperation])
4296
4297 c.clear_flags()
4298 q, r = divmod(Decimal(0), 0)
4299 self.assertTrue(q.is_nan() and r.is_nan())
4300 self.assertTrue(c.flags[InvalidOperation])
4301
4302 c.traps[DivisionByZero] = False
4303 c.clear_flags()
4304 q, r = divmod(Decimal(11), 0)
4305 self.assertTrue(q.is_infinite() and r.is_nan())
4306 self.assertTrue(c.flags[InvalidOperation] and
4307 c.flags[DivisionByZero])
4308
4309 def test_power(self):
4310 Decimal = self.decimal.Decimal
4311 localcontext = self.decimal.localcontext
4312 Overflow = self.decimal.Overflow
4313 Rounded = self.decimal.Rounded
4314
4315 with localcontext() as c:
4316 c.prec = 3
4317 c.clear_flags()
4318 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4319 self.assertTrue(c.flags[Rounded])
4320
4321 c.prec = 1
4322 c.Emax = 1
4323 c.Emin = -1
4324 c.clear_flags()
4325 c.traps[Overflow] = False
4326 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4327 self.assertTrue(c.flags[Overflow])
4328
4329 def test_quantize(self):
4330 Decimal = self.decimal.Decimal
4331 localcontext = self.decimal.localcontext
4332 InvalidOperation = self.decimal.InvalidOperation
4333
4334 with localcontext() as c:
4335 c.prec = 1
4336 c.Emax = 1
4337 c.Emin = -1
4338 c.traps[InvalidOperation] = False
4339 x = Decimal(99).quantize(Decimal("1e1"))
4340 self.assertTrue(x.is_nan())
4341
4342 def test_radix(self):
4343 Decimal = self.decimal.Decimal
4344 getcontext = self.decimal.getcontext
4345
4346 c = getcontext()
4347 self.assertEqual(Decimal("1").radix(), 10)
4348 self.assertEqual(c.radix(), 10)
4349
4350 def test_rop(self):
4351 Decimal = self.decimal.Decimal
4352
4353 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4354 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4355 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4356
4357 def test_round(self):
4358 # Python3 behavior: round() returns Decimal
4359 Decimal = self.decimal.Decimal
4360 getcontext = self.decimal.getcontext
4361
4362 c = getcontext()
4363 c.prec = 28
4364
4365 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4366 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4367 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4368 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4369 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4370
4371 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4372 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4373
4374 def test_create_decimal(self):
4375 c = self.decimal.Context()
4376 self.assertRaises(ValueError, c.create_decimal, ["%"])
4377
4378 def test_int(self):
4379 Decimal = self.decimal.Decimal
4380 localcontext = self.decimal.localcontext
4381
4382 with localcontext() as c:
4383 c.prec = 9999
4384 x = Decimal(1221**1271) / 10**3923
4385 self.assertEqual(int(x), 1)
4386 self.assertEqual(x.to_integral(), 2)
4387
4388 def test_copy(self):
4389 Context = self.decimal.Context
4390
4391 c = Context()
4392 c.prec = 10000
4393 x = -(1172 ** 1712)
4394
4395 y = c.copy_abs(x)
4396 self.assertEqual(y, -x)
4397
4398 y = c.copy_negate(x)
4399 self.assertEqual(y, -x)
4400
4401 y = c.copy_sign(x, 1)
4402 self.assertEqual(y, -x)
4403
4404class CCoverage(Coverage):
4405 decimal = C
4406class PyCoverage(Coverage):
4407 decimal = P
4408
4409class PyFunctionality(unittest.TestCase):
4410 """Extra functionality in decimal.py"""
4411
4412 def test_py_quantize_watchexp(self):
4413 # watchexp functionality
4414 Decimal = P.Decimal
4415 localcontext = P.localcontext
4416
4417 with localcontext() as c:
4418 c.prec = 1
4419 c.Emax = 1
4420 c.Emin = -1
4421 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4422 self.assertEqual(x, Decimal('1.00E+5'))
4423
4424 def test_py_alternate_formatting(self):
4425 # triples giving a format, a Decimal, and the expected result
4426 Decimal = P.Decimal
4427 localcontext = P.localcontext
4428
4429 test_values = [
4430 # Issue 7094: Alternate formatting (specified by #)
4431 ('.0e', '1.0', '1e+0'),
4432 ('#.0e', '1.0', '1.e+0'),
4433 ('.0f', '1.0', '1'),
4434 ('#.0f', '1.0', '1.'),
4435 ('g', '1.1', '1.1'),
4436 ('#g', '1.1', '1.1'),
4437 ('.0g', '1', '1'),
4438 ('#.0g', '1', '1.'),
4439 ('.0%', '1.0', '100%'),
4440 ('#.0%', '1.0', '100.%'),
4441 ]
4442 for fmt, d, result in test_values:
4443 self.assertEqual(format(Decimal(d), fmt), result)
4444
4445class PyWhitebox(unittest.TestCase):
4446 """White box testing for decimal.py"""
4447
4448 def test_py_exact_power(self):
4449 # Rarely exercised lines in _power_exact.
4450 Decimal = P.Decimal
4451 localcontext = P.localcontext
4452
4453 with localcontext() as c:
4454 c.prec = 8
4455 x = Decimal(2**16) ** Decimal("-0.5")
4456 self.assertEqual(x, Decimal('0.00390625'))
4457
4458 x = Decimal(2**16) ** Decimal("-0.6")
4459 self.assertEqual(x, Decimal('0.0012885819'))
4460
4461 x = Decimal("256e7") ** Decimal("-0.5")
4462
4463 x = Decimal(152587890625) ** Decimal('-0.0625')
4464 self.assertEqual(x, Decimal("0.2"))
4465
4466 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4467
4468 x = Decimal(5**2659) ** Decimal('-0.0625')
4469
4470 c.prec = 1
4471 x = Decimal("152587890625") ** Decimal('-0.5')
4472 c.prec = 201
4473 x = Decimal(2**578) ** Decimal("-0.5")
4474
4475 def test_py_immutability_operations(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004476 # Do operations and check that it didn't change change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004477 Decimal = P.Decimal
4478 DefaultContext = P.DefaultContext
4479 setcontext = P.setcontext
4480
4481 c = DefaultContext.copy()
4482 c.traps = dict((s, 0) for s in OrderedSignals[P])
4483 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004484
4485 d1 = Decimal('-25e55')
4486 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004487 d2 = Decimal('33e+33')
4488 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004489
4490 def checkSameDec(operation, useOther=False):
4491 if useOther:
4492 eval("d1." + operation + "(d2)")
4493 self.assertEqual(d1._sign, b1._sign)
4494 self.assertEqual(d1._int, b1._int)
4495 self.assertEqual(d1._exp, b1._exp)
4496 self.assertEqual(d2._sign, b2._sign)
4497 self.assertEqual(d2._int, b2._int)
4498 self.assertEqual(d2._exp, b2._exp)
4499 else:
4500 eval("d1." + operation + "()")
4501 self.assertEqual(d1._sign, b1._sign)
4502 self.assertEqual(d1._int, b1._int)
4503 self.assertEqual(d1._exp, b1._exp)
4504 return
4505
4506 Decimal(d1)
4507 self.assertEqual(d1._sign, b1._sign)
4508 self.assertEqual(d1._int, b1._int)
4509 self.assertEqual(d1._exp, b1._exp)
4510
4511 checkSameDec("__abs__")
4512 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004513 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004514 checkSameDec("__eq__", True)
4515 checkSameDec("__ne__", True)
4516 checkSameDec("__le__", True)
4517 checkSameDec("__lt__", True)
4518 checkSameDec("__ge__", True)
4519 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004520 checkSameDec("__float__")
4521 checkSameDec("__floordiv__", True)
4522 checkSameDec("__hash__")
4523 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004524 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004525 checkSameDec("__mod__", True)
4526 checkSameDec("__mul__", True)
4527 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004528 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004529 checkSameDec("__pos__")
4530 checkSameDec("__pow__", True)
4531 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004532 checkSameDec("__rdivmod__", True)
4533 checkSameDec("__repr__")
4534 checkSameDec("__rfloordiv__", True)
4535 checkSameDec("__rmod__", True)
4536 checkSameDec("__rmul__", True)
4537 checkSameDec("__rpow__", True)
4538 checkSameDec("__rsub__", True)
4539 checkSameDec("__str__")
4540 checkSameDec("__sub__", True)
4541 checkSameDec("__truediv__", True)
4542 checkSameDec("adjusted")
4543 checkSameDec("as_tuple")
4544 checkSameDec("compare", True)
4545 checkSameDec("max", True)
4546 checkSameDec("min", True)
4547 checkSameDec("normalize")
4548 checkSameDec("quantize", True)
4549 checkSameDec("remainder_near", True)
4550 checkSameDec("same_quantum", True)
4551 checkSameDec("sqrt")
4552 checkSameDec("to_eng_string")
4553 checkSameDec("to_integral")
4554
Stefan Krah1919b7e2012-03-21 18:25:23 +01004555 def test_py_decimal_id(self):
4556 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004557
Stefan Krah1919b7e2012-03-21 18:25:23 +01004558 d = Decimal(45)
4559 e = Decimal(d)
4560 self.assertEqual(str(e), '45')
4561 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004562
Stefan Krah1919b7e2012-03-21 18:25:23 +01004563 def test_py_rescale(self):
4564 # Coverage
4565 Decimal = P.Decimal
4566 ROUND_UP = P.ROUND_UP
4567 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004568
Stefan Krah1919b7e2012-03-21 18:25:23 +01004569 with localcontext() as c:
4570 x = Decimal("NaN")._rescale(3, ROUND_UP)
4571 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004572
Stefan Krah1919b7e2012-03-21 18:25:23 +01004573 def test_py__round(self):
4574 # Coverage
4575 Decimal = P.Decimal
4576 ROUND_UP = P.ROUND_UP
Christian Heimes0348fb62008-03-26 12:55:56 +00004577
Stefan Krah1919b7e2012-03-21 18:25:23 +01004578 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004579
Stefan Krah1919b7e2012-03-21 18:25:23 +01004580class CFunctionality(unittest.TestCase):
4581 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004582
Stefan Krah1919b7e2012-03-21 18:25:23 +01004583 @requires_extra_functionality
4584 def test_c_ieee_context(self):
4585 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4586 IEEEContext = C.IEEEContext
4587 DECIMAL32 = C.DECIMAL32
4588 DECIMAL64 = C.DECIMAL64
4589 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004590
Stefan Krah1919b7e2012-03-21 18:25:23 +01004591 def assert_rest(self, context):
4592 self.assertEqual(context.clamp, 1)
4593 assert_signals(self, context, 'traps', [])
4594 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004595
Stefan Krah1919b7e2012-03-21 18:25:23 +01004596 c = IEEEContext(DECIMAL32)
4597 self.assertEqual(c.prec, 7)
4598 self.assertEqual(c.Emax, 96)
4599 self.assertEqual(c.Emin, -95)
4600 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004601
Stefan Krah1919b7e2012-03-21 18:25:23 +01004602 c = IEEEContext(DECIMAL64)
4603 self.assertEqual(c.prec, 16)
4604 self.assertEqual(c.Emax, 384)
4605 self.assertEqual(c.Emin, -383)
4606 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004607
Stefan Krah1919b7e2012-03-21 18:25:23 +01004608 c = IEEEContext(DECIMAL128)
4609 self.assertEqual(c.prec, 34)
4610 self.assertEqual(c.Emax, 6144)
4611 self.assertEqual(c.Emin, -6143)
4612 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004613
Stefan Krah1919b7e2012-03-21 18:25:23 +01004614 # Invalid values
4615 self.assertRaises(OverflowError, IEEEContext, 2**63)
4616 self.assertRaises(ValueError, IEEEContext, -1)
4617 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004618
Stefan Krah1919b7e2012-03-21 18:25:23 +01004619 @requires_extra_functionality
4620 def test_c_context(self):
4621 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004622
Stefan Krah1919b7e2012-03-21 18:25:23 +01004623 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4624 self.assertEqual(c._flags, C.DecClamped)
4625 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004626
Stefan Krah1919b7e2012-03-21 18:25:23 +01004627 @requires_extra_functionality
4628 def test_constants(self):
4629 # Condition flags
4630 cond = (
4631 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4632 C.DecDivisionImpossible, C.DecDivisionUndefined,
4633 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4634 C.DecInvalidOperation, C.DecMallocError,
4635 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4636 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004637 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004638
4639 # IEEEContext
4640 self.assertEqual(C.DECIMAL32, 32)
4641 self.assertEqual(C.DECIMAL64, 64)
4642 self.assertEqual(C.DECIMAL128, 128)
4643 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4644
4645 # Rounding modes
4646 for i, v in enumerate(RoundingModes[C]):
4647 self.assertEqual(v, i)
4648 self.assertEqual(C.ROUND_TRUNC, 8)
4649
4650 # Conditions
4651 for i, v in enumerate(cond):
4652 self.assertEqual(v, 1<<i)
4653
4654 self.assertEqual(C.DecIEEEInvalidOperation,
4655 C.DecConversionSyntax|
4656 C.DecDivisionImpossible|
4657 C.DecDivisionUndefined|
4658 C.DecFpuError|
4659 C.DecInvalidContext|
4660 C.DecInvalidOperation|
4661 C.DecMallocError)
4662
4663 self.assertEqual(C.DecErrors,
4664 C.DecIEEEInvalidOperation|
4665 C.DecDivisionByZero)
4666
4667 self.assertEqual(C.DecTraps,
4668 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4669
4670class CWhitebox(unittest.TestCase):
4671 """Whitebox testing for _decimal"""
4672
4673 def test_bignum(self):
4674 # Not exactly whitebox, but too slow with pydecimal.
4675
4676 Decimal = C.Decimal
4677 localcontext = C.localcontext
4678
4679 b1 = 10**35
4680 b2 = 10**36
4681 with localcontext() as c:
4682 c.prec = 1000000
4683 for i in range(5):
4684 a = random.randrange(b1, b2)
4685 b = random.randrange(1000, 1200)
4686 x = a ** b
4687 y = Decimal(a) ** Decimal(b)
4688 self.assertEqual(x, y)
4689
4690 def test_invalid_construction(self):
4691 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4692
4693 def test_c_input_restriction(self):
4694 # Too large for _decimal to be converted exactly
4695 Decimal = C.Decimal
4696 InvalidOperation = C.InvalidOperation
4697 Context = C.Context
4698 localcontext = C.localcontext
4699
4700 with localcontext(Context()):
4701 self.assertRaises(InvalidOperation, Decimal,
4702 "1e9999999999999999999")
4703
4704 def test_c_context_repr(self):
4705 # This test is _decimal-only because flags are not printed
4706 # in the same order.
4707 DefaultContext = C.DefaultContext
4708 FloatOperation = C.FloatOperation
4709 ROUND_HALF_DOWN = C.ROUND_HALF_DOWN
4710
4711 c = DefaultContext.copy()
4712
4713 c.prec = 425000000
4714 c.Emax = 425000000
4715 c.Emin = -425000000
4716 c.rounding = ROUND_HALF_DOWN
4717 c.capitals = 0
4718 c.clamp = 1
4719 for sig in OrderedSignals[C]:
4720 c.flags[sig] = True
4721 c.traps[sig] = True
4722 c.flags[FloatOperation] = True
4723 c.traps[FloatOperation] = True
4724
4725 s = c.__repr__()
4726 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4727 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4728 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4729 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4730 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4731 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4732 self.assertEqual(s, t)
4733
4734 def test_c_context_errors(self):
4735 Context = C.Context
4736 InvalidOperation = C.InvalidOperation
4737 Overflow = C.Overflow
4738 FloatOperation = C.FloatOperation
4739 localcontext = C.localcontext
4740 getcontext = C.getcontext
4741 setcontext = C.setcontext
4742 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4743
4744 c = Context()
4745
4746 # SignalDict: input validation
4747 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4748 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4749 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4750 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4751 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4752 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4753 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4754 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4755
4756 # Test assignment from a signal dict with the correct length but
4757 # one invalid key.
4758 d = c.flags.copy()
4759 del d[FloatOperation]
4760 d["XYZ"] = 91283719
4761 self.assertRaises(KeyError, setattr, c, 'flags', d)
4762 self.assertRaises(KeyError, setattr, c, 'traps', d)
4763
4764 # Input corner cases
4765 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4766 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4767
4768 # prec, Emax, Emin
4769 for attr in ['prec', 'Emax']:
4770 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4771 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4772
4773 # prec, Emax, Emin in context constructor
4774 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4775 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4776 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4777
4778 # Overflow in conversion
4779 self.assertRaises(OverflowError, Context, prec=int_max+1)
4780 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4781 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
4782 self.assertRaises(OverflowError, Context, rounding=int_max+1)
4783 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4784 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4785
4786 # OverflowError, general ValueError
4787 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4788 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4789 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4790 if sys.platform != 'win32':
4791 self.assertRaises(ValueError, setattr, c, attr, int_max)
4792 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4793
4794 # OverflowError, general TypeError
4795 for attr in ('rounding',):
4796 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4797 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4798 if sys.platform != 'win32':
4799 self.assertRaises(TypeError, setattr, c, attr, int_max)
4800 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4801
4802 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4803 if C.MAX_PREC == 425000000:
4804 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4805 int_max+1)
4806 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4807 int_max+1)
4808 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4809 -int_max-2)
4810
4811 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4812 if C.MAX_PREC == 425000000:
4813 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4814 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4815 1070000001)
4816 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4817 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4818 1070000001)
4819 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4820 -1070000001)
4821 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4822
4823 # capitals, clamp
4824 for attr in ['capitals', 'clamp']:
4825 self.assertRaises(ValueError, setattr, c, attr, -1)
4826 self.assertRaises(ValueError, setattr, c, attr, 2)
4827 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4828 if HAVE_CONFIG_64:
4829 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4830 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4831
4832 # Invalid local context
4833 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4834 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004835 self.assertRaises(TypeError, exec,
4836 'with localcontext(context=getcontext()): pass',
4837 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004838
4839 # setcontext
4840 saved_context = getcontext()
4841 self.assertRaises(TypeError, setcontext, "xyz")
4842 setcontext(saved_context)
4843
4844 @requires_extra_functionality
4845 def test_c_context_errors_extra(self):
4846 Context = C.Context
4847 InvalidOperation = C.InvalidOperation
4848 Overflow = C.Overflow
4849 localcontext = C.localcontext
4850 getcontext = C.getcontext
4851 setcontext = C.setcontext
4852 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4853
4854 c = Context()
4855
4856 # Input corner cases
4857 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4858
4859 # OverflowError, general ValueError
4860 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4861 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4862 if sys.platform != 'win32':
4863 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4864 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4865
4866 # OverflowError, general TypeError
4867 for attr in ('_flags', '_traps'):
4868 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4869 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4870 if sys.platform != 'win32':
4871 self.assertRaises(TypeError, setattr, c, attr, int_max)
4872 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4873
4874 # _allcr
4875 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4876 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4877 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4878 if HAVE_CONFIG_64:
4879 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4880 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4881
4882 # _flags, _traps
4883 for attr in ['_flags', '_traps']:
4884 self.assertRaises(TypeError, setattr, c, attr, 999999)
4885 self.assertRaises(TypeError, setattr, c, attr, 'x')
4886
4887 def test_c_valid_context(self):
4888 # These tests are for code coverage in _decimal.
4889 DefaultContext = C.DefaultContext
4890 ROUND_HALF_UP = C.ROUND_HALF_UP
4891 Clamped = C.Clamped
4892 Underflow = C.Underflow
4893 Inexact = C.Inexact
4894 Rounded = C.Rounded
4895 Subnormal = C.Subnormal
4896
4897 c = DefaultContext.copy()
4898
4899 # Exercise all getters and setters
4900 c.prec = 34
4901 c.rounding = ROUND_HALF_UP
4902 c.Emax = 3000
4903 c.Emin = -3000
4904 c.capitals = 1
4905 c.clamp = 0
4906
4907 self.assertEqual(c.prec, 34)
4908 self.assertEqual(c.rounding, ROUND_HALF_UP)
4909 self.assertEqual(c.Emin, -3000)
4910 self.assertEqual(c.Emax, 3000)
4911 self.assertEqual(c.capitals, 1)
4912 self.assertEqual(c.clamp, 0)
4913
4914 self.assertEqual(c.Etiny(), -3033)
4915 self.assertEqual(c.Etop(), 2967)
4916
4917 # Exercise all unsafe setters
4918 if C.MAX_PREC == 425000000:
4919 c._unsafe_setprec(999999999)
4920 c._unsafe_setemax(999999999)
4921 c._unsafe_setemin(-999999999)
4922 self.assertEqual(c.prec, 999999999)
4923 self.assertEqual(c.Emax, 999999999)
4924 self.assertEqual(c.Emin, -999999999)
4925
4926 @requires_extra_functionality
4927 def test_c_valid_context_extra(self):
4928 DefaultContext = C.DefaultContext
4929
4930 c = DefaultContext.copy()
4931 self.assertEqual(c._allcr, 1)
4932 c._allcr = 0
4933 self.assertEqual(c._allcr, 0)
4934
4935 def test_c_round(self):
4936 # Restricted input.
4937 Decimal = C.Decimal
4938 InvalidOperation = C.InvalidOperation
4939 localcontext = C.localcontext
4940 MAX_EMAX = C.MAX_EMAX
4941 MIN_ETINY = C.MIN_ETINY
4942 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4943
4944 with localcontext() as c:
4945 c.traps[InvalidOperation] = True
4946 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4947 -int_max-1)
4948 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4949 int_max)
4950 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4951 int(MAX_EMAX+1))
4952 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4953 -int(MIN_ETINY-1))
4954 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4955 -int_max-2)
4956 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4957 int_max+1)
4958
4959 def test_c_format(self):
4960 # Restricted input
4961 Decimal = C.Decimal
4962 InvalidOperation = C.InvalidOperation
4963 Rounded = C.Rounded
4964 localcontext = C.localcontext
4965 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4966
4967 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4968 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4969 self.assertRaises(TypeError, Decimal(1).__format__, [])
4970
4971 with localcontext() as c:
4972 c.traps[InvalidOperation] = True
4973 c.traps[Rounded] = True
4974 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4975 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4976 self.assertRaises(InvalidOperation, Decimal("1.23456789").__format__,
4977 "=%d.1" % maxsize)
4978
4979 def test_c_integral(self):
4980 Decimal = C.Decimal
4981 Inexact = C.Inexact
4982 ROUND_UP = C.ROUND_UP
4983 localcontext = C.localcontext
4984
4985 x = Decimal(10)
4986 self.assertEqual(x.to_integral(), 10)
4987 self.assertRaises(TypeError, x.to_integral, '10')
4988 self.assertRaises(TypeError, x.to_integral, 10, 'x')
4989 self.assertRaises(TypeError, x.to_integral, 10)
4990
4991 self.assertEqual(x.to_integral_value(), 10)
4992 self.assertRaises(TypeError, x.to_integral_value, '10')
4993 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
4994 self.assertRaises(TypeError, x.to_integral_value, 10)
4995
4996 self.assertEqual(x.to_integral_exact(), 10)
4997 self.assertRaises(TypeError, x.to_integral_exact, '10')
4998 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
4999 self.assertRaises(TypeError, x.to_integral_exact, 10)
5000
5001 with localcontext() as c:
5002 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5003 self.assertEqual(x, Decimal('100000000000000000000000000'))
5004
5005 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5006 self.assertEqual(x, Decimal('100000000000000000000000000'))
5007
5008 c.traps[Inexact] = True
5009 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5010
5011 def test_c_funcs(self):
5012 # Invalid arguments
5013 Decimal = C.Decimal
5014 InvalidOperation = C.InvalidOperation
5015 DivisionByZero = C.DivisionByZero
5016 ROUND_UP = C.ROUND_UP
5017 getcontext = C.getcontext
5018 localcontext = C.localcontext
5019
5020 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5021
5022 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5023 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5024 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5025
Raymond Hettinger771ed762009-01-03 19:20:32 +00005026 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005027 TypeError,
5028 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005029 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005030 self.assertRaises(
5031 TypeError,
5032 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5033 )
5034 self.assertRaises(
5035 TypeError,
5036 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5037 )
5038 self.assertRaises(
5039 TypeError,
5040 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5041 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005042
Stefan Krah1919b7e2012-03-21 18:25:23 +01005043 with localcontext() as c:
5044 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005045
Stefan Krah1919b7e2012-03-21 18:25:23 +01005046 # Invalid arguments
5047 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5048 self.assertRaises(TypeError, c.canonical, 200)
5049 self.assertRaises(TypeError, c.is_canonical, 200)
5050 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5051 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005052
Stefan Krah1919b7e2012-03-21 18:25:23 +01005053 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5054 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005055
Stefan Krah1919b7e2012-03-21 18:25:23 +01005056 c.traps[DivisionByZero] = True
5057 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5058 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5059 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005060
Stefan Krah1919b7e2012-03-21 18:25:23 +01005061 c.clear_flags()
5062 c.traps[InvalidOperation] = True
5063 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5064 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5065 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005066
Stefan Krah1919b7e2012-03-21 18:25:23 +01005067 c.traps[InvalidOperation] = True
5068 c.prec = 2
5069 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005070
Stefan Krah040e3112012-12-15 22:33:33 +01005071 def test_va_args_exceptions(self):
5072 Decimal = C.Decimal
5073 Context = C.Context
5074
5075 x = Decimal("10001111111")
5076
5077 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5078 'logb', 'logical_invert', 'next_minus', 'next_plus',
5079 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5080 func = getattr(x, attr)
5081 self.assertRaises(TypeError, func, context="x")
5082 self.assertRaises(TypeError, func, "x", context=None)
5083
5084 for attr in ['compare', 'compare_signal', 'logical_and',
5085 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5086 'remainder_near', 'rotate', 'scaleb', 'shift']:
5087 func = getattr(x, attr)
5088 self.assertRaises(TypeError, func, context="x")
5089 self.assertRaises(TypeError, func, "x", context=None)
5090
5091 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5092 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5093 self.assertRaises(TypeError, x.to_integral, [], [])
5094
5095 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5096 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5097 self.assertRaises(TypeError, x.to_integral_value, [], [])
5098
5099 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5100 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5101 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5102
5103 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5104 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5105
5106 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5107 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5108 self.assertRaises(TypeError, x.quantize, 1, [], [])
5109
5110 c = Context()
5111 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5112 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5113 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5114
Stefan Krah1919b7e2012-03-21 18:25:23 +01005115 @requires_extra_functionality
5116 def test_c_context_templates(self):
5117 self.assertEqual(
5118 C.BasicContext._traps,
5119 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5120 C.DecUnderflow|C.DecClamped
5121 )
5122 self.assertEqual(
5123 C.DefaultContext._traps,
5124 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5125 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005126
Stefan Krah1919b7e2012-03-21 18:25:23 +01005127 @requires_extra_functionality
5128 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005129
Stefan Krah1919b7e2012-03-21 18:25:23 +01005130 # SignalDict coverage
5131 Context = C.Context
5132 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005133
Stefan Krah1919b7e2012-03-21 18:25:23 +01005134 InvalidOperation = C.InvalidOperation
5135 DivisionByZero = C.DivisionByZero
5136 Overflow = C.Overflow
5137 Subnormal = C.Subnormal
5138 Underflow = C.Underflow
5139 Rounded = C.Rounded
5140 Inexact = C.Inexact
5141 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005142
Stefan Krah1919b7e2012-03-21 18:25:23 +01005143 DecClamped = C.DecClamped
5144 DecInvalidOperation = C.DecInvalidOperation
5145 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005146
Stefan Krah1919b7e2012-03-21 18:25:23 +01005147 def assertIsExclusivelySet(signal, signal_dict):
5148 for sig in signal_dict:
5149 if sig == signal:
5150 self.assertTrue(signal_dict[sig])
5151 else:
5152 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005153
Stefan Krah1919b7e2012-03-21 18:25:23 +01005154 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005155
Stefan Krah1919b7e2012-03-21 18:25:23 +01005156 # Signal dict methods
5157 self.assertTrue(Overflow in c.traps)
5158 c.clear_traps()
5159 for k in c.traps.keys():
5160 c.traps[k] = True
5161 for v in c.traps.values():
5162 self.assertTrue(v)
5163 c.clear_traps()
5164 for k, v in c.traps.items():
5165 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005166
Stefan Krah1919b7e2012-03-21 18:25:23 +01005167 self.assertFalse(c.flags.get(Overflow))
5168 self.assertIs(c.flags.get("x"), None)
5169 self.assertEqual(c.flags.get("x", "y"), "y")
5170 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005171
Stefan Krah1919b7e2012-03-21 18:25:23 +01005172 self.assertEqual(len(c.flags), len(c.traps))
5173 s = sys.getsizeof(c.flags)
5174 s = sys.getsizeof(c.traps)
5175 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005176
Stefan Krah1919b7e2012-03-21 18:25:23 +01005177 # Set flags/traps.
5178 c.clear_flags()
5179 c._flags = DecClamped
5180 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005181
Stefan Krah1919b7e2012-03-21 18:25:23 +01005182 c.clear_traps()
5183 c._traps = DecInvalidOperation
5184 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005185
Stefan Krah1919b7e2012-03-21 18:25:23 +01005186 # Set flags/traps from dictionary.
5187 c.clear_flags()
5188 d = c.flags.copy()
5189 d[DivisionByZero] = True
5190 c.flags = d
5191 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005192
Stefan Krah1919b7e2012-03-21 18:25:23 +01005193 c.clear_traps()
5194 d = c.traps.copy()
5195 d[Underflow] = True
5196 c.traps = d
5197 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005198
Stefan Krah1919b7e2012-03-21 18:25:23 +01005199 # Random constructors
5200 IntSignals = {
5201 Clamped: C.DecClamped,
5202 Rounded: C.DecRounded,
5203 Inexact: C.DecInexact,
5204 Subnormal: C.DecSubnormal,
5205 Underflow: C.DecUnderflow,
5206 Overflow: C.DecOverflow,
5207 DivisionByZero: C.DecDivisionByZero,
5208 InvalidOperation: C.DecIEEEInvalidOperation
5209 }
5210 IntCond = [
5211 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5212 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5213 C.DecConversionSyntax,
5214 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005215
Stefan Krah1919b7e2012-03-21 18:25:23 +01005216 lim = len(OrderedSignals[C])
5217 for r in range(lim):
5218 for t in range(lim):
5219 for round in RoundingModes[C]:
5220 flags = random.sample(OrderedSignals[C], r)
5221 traps = random.sample(OrderedSignals[C], t)
5222 prec = random.randrange(1, 10000)
5223 emin = random.randrange(-10000, 0)
5224 emax = random.randrange(0, 10000)
5225 clamp = random.randrange(0, 2)
5226 caps = random.randrange(0, 2)
5227 cr = random.randrange(0, 2)
5228 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5229 capitals=caps, clamp=clamp, flags=list(flags),
5230 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005231
Stefan Krah1919b7e2012-03-21 18:25:23 +01005232 self.assertEqual(c.prec, prec)
5233 self.assertEqual(c.rounding, round)
5234 self.assertEqual(c.Emin, emin)
5235 self.assertEqual(c.Emax, emax)
5236 self.assertEqual(c.capitals, caps)
5237 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005238
Stefan Krah1919b7e2012-03-21 18:25:23 +01005239 f = 0
5240 for x in flags:
5241 f |= IntSignals[x]
5242 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005243
Stefan Krah1919b7e2012-03-21 18:25:23 +01005244 f = 0
5245 for x in traps:
5246 f |= IntSignals[x]
5247 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005248
Stefan Krah1919b7e2012-03-21 18:25:23 +01005249 for cond in IntCond:
5250 c._flags = cond
5251 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5252 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005253
Stefan Krah1919b7e2012-03-21 18:25:23 +01005254 for cond in IntCond:
5255 c._traps = cond
5256 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5257 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005258
Stefan Krah1919b7e2012-03-21 18:25:23 +01005259 def test_invalid_override(self):
5260 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005261
Stefan Krah1919b7e2012-03-21 18:25:23 +01005262 try:
5263 from locale import CHAR_MAX
5264 except ImportError:
5265 return
Mark Dickinson84230a12010-02-18 14:49:50 +00005266
Stefan Krah1919b7e2012-03-21 18:25:23 +01005267 def make_grouping(lst):
5268 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005269
Stefan Krah1919b7e2012-03-21 18:25:23 +01005270 def get_fmt(x, override=None, fmt='n'):
5271 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005272
Stefan Krah1919b7e2012-03-21 18:25:23 +01005273 invalid_grouping = {
5274 'decimal_point' : ',',
5275 'grouping' : make_grouping([255, 255, 0]),
5276 'thousands_sep' : ','
5277 }
5278 invalid_dot = {
5279 'decimal_point' : 'xxxxx',
5280 'grouping' : make_grouping([3, 3, 0]),
5281 'thousands_sep' : ','
5282 }
5283 invalid_sep = {
5284 'decimal_point' : '.',
5285 'grouping' : make_grouping([3, 3, 0]),
5286 'thousands_sep' : 'yyyyy'
5287 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005288
Stefan Krah1919b7e2012-03-21 18:25:23 +01005289 if CHAR_MAX == 127: # negative grouping in override
5290 self.assertRaises(ValueError, get_fmt, 12345,
5291 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005292
Stefan Krah1919b7e2012-03-21 18:25:23 +01005293 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5294 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005295
Stefan Krah0774e9b2012-04-05 15:21:58 +02005296 def test_exact_conversion(self):
5297 Decimal = C.Decimal
5298 localcontext = C.localcontext
5299 InvalidOperation = C.InvalidOperation
5300
5301 with localcontext() as c:
5302
5303 c.traps[InvalidOperation] = True
5304
5305 # Clamped
5306 x = "0e%d" % sys.maxsize
5307 self.assertRaises(InvalidOperation, Decimal, x)
5308
5309 x = "0e%d" % (-sys.maxsize-1)
5310 self.assertRaises(InvalidOperation, Decimal, x)
5311
5312 # Overflow
5313 x = "1e%d" % sys.maxsize
5314 self.assertRaises(InvalidOperation, Decimal, x)
5315
5316 # Underflow
5317 x = "1e%d" % (-sys.maxsize-1)
5318 self.assertRaises(InvalidOperation, Decimal, x)
5319
Stefan Krahff3eca02012-04-05 15:46:19 +02005320 def test_from_tuple(self):
5321 Decimal = C.Decimal
5322 localcontext = C.localcontext
5323 InvalidOperation = C.InvalidOperation
5324 Overflow = C.Overflow
5325 Underflow = C.Underflow
5326
5327 with localcontext() as c:
5328
5329 c.traps[InvalidOperation] = True
5330 c.traps[Overflow] = True
5331 c.traps[Underflow] = True
5332
5333 # SSIZE_MAX
5334 x = (1, (), sys.maxsize)
5335 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5336 self.assertRaises(InvalidOperation, Decimal, x)
5337
5338 x = (1, (0, 1, 2), sys.maxsize)
5339 self.assertRaises(Overflow, c.create_decimal, x)
5340 self.assertRaises(InvalidOperation, Decimal, x)
5341
5342 # SSIZE_MIN
5343 x = (1, (), -sys.maxsize-1)
5344 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5345 self.assertRaises(InvalidOperation, Decimal, x)
5346
5347 x = (1, (0, 1, 2), -sys.maxsize-1)
5348 self.assertRaises(Underflow, c.create_decimal, x)
5349 self.assertRaises(InvalidOperation, Decimal, x)
5350
5351 # OverflowError
5352 x = (1, (), sys.maxsize+1)
5353 self.assertRaises(OverflowError, c.create_decimal, x)
5354 self.assertRaises(OverflowError, Decimal, x)
5355
5356 x = (1, (), -sys.maxsize-2)
5357 self.assertRaises(OverflowError, c.create_decimal, x)
5358 self.assertRaises(OverflowError, Decimal, x)
5359
5360 # Specials
5361 x = (1, (), "N")
5362 self.assertEqual(str(Decimal(x)), '-sNaN')
5363 x = (1, (0,), "N")
5364 self.assertEqual(str(Decimal(x)), '-sNaN')
5365 x = (1, (0, 1), "N")
5366 self.assertEqual(str(Decimal(x)), '-sNaN1')
5367
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005368
Stefan Krah1919b7e2012-03-21 18:25:23 +01005369all_tests = [
5370 CExplicitConstructionTest, PyExplicitConstructionTest,
5371 CImplicitConstructionTest, PyImplicitConstructionTest,
5372 CFormatTest, PyFormatTest,
5373 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5374 CThreadingTest, PyThreadingTest,
5375 CUsabilityTest, PyUsabilityTest,
5376 CPythonAPItests, PyPythonAPItests,
5377 CContextAPItests, PyContextAPItests,
5378 CContextWithStatement, PyContextWithStatement,
5379 CContextFlags, PyContextFlags,
5380 CSpecialContexts, PySpecialContexts,
5381 CContextInputValidation, PyContextInputValidation,
5382 CContextSubclassing, PyContextSubclassing,
5383 CCoverage, PyCoverage,
5384 CFunctionality, PyFunctionality,
5385 CWhitebox, PyWhitebox,
5386 CIBMTestCases, PyIBMTestCases,
5387]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005388
Stefan Krah1919b7e2012-03-21 18:25:23 +01005389# Delete C tests if _decimal.so is not present.
5390if not C:
5391 all_tests = all_tests[1::2]
5392else:
5393 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005394
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005395
5396def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005397 """ Execute the tests.
5398
Raymond Hettingered20ad82004-09-04 20:09:13 +00005399 Runs all arithmetic tests if arith is True or if the "decimal" resource
5400 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005401 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005402
Stefan Krah1919b7e2012-03-21 18:25:23 +01005403 init(C)
5404 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005405 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00005406 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005407 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005408
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005409 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005410 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005411 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005412 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005413
5414 # Dynamically build custom test definition for each file in the test
5415 # directory and add the definitions to the DecimalTest class. This
5416 # procedure insures that new files do not get skipped.
5417 for filename in os.listdir(directory):
5418 if '.decTest' not in filename or filename.startswith("."):
5419 continue
5420 head, tail = filename.split('.')
5421 if todo_tests is not None and head not in todo_tests:
5422 continue
5423 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005424 setattr(CIBMTestCases, 'test_' + head, tester)
5425 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005426 del filename, head, tail, tester
5427
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005428
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005429 try:
5430 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005431 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005432 from doctest import IGNORE_EXCEPTION_DETAIL
5433 savedecimal = sys.modules['decimal']
5434 if C:
5435 sys.modules['decimal'] = C
5436 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5437 sys.modules['decimal'] = P
5438 run_doctest(P, verbose)
5439 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005440 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005441 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5442 P.setcontext(ORIGINAL_CONTEXT[P])
5443 if not C:
5444 warnings.warn('C tests skipped: no module named _decimal.',
5445 UserWarning)
5446 if not orig_sys_decimal is sys.modules['decimal']:
5447 raise TestFailed("Internal error: unbalanced number of changes to "
5448 "sys.modules['decimal'].")
5449
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005450
5451if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005452 import optparse
5453 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5454 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5455 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5456 (opt, args) = p.parse_args()
5457
5458 if opt.skip:
5459 test_main(arith=False, verbose=True)
5460 elif args:
5461 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005462 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005463 test_main(arith=True, verbose=True)