blob: 50a9ad4362b6a6469bd9a84fa53492ad2d26b327 [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
Stefan Krah59a4a932013-01-16 12:58:59 +010081ROUND_UP = P.ROUND_UP
82ROUND_DOWN = P.ROUND_DOWN
83ROUND_CEILING = P.ROUND_CEILING
84ROUND_FLOOR = P.ROUND_FLOOR
85ROUND_HALF_UP = P.ROUND_HALF_UP
86ROUND_HALF_DOWN = P.ROUND_HALF_DOWN
87ROUND_HALF_EVEN = P.ROUND_HALF_EVEN
88ROUND_05UP = P.ROUND_05UP
89
90RoundingModes = [
91 ROUND_UP, ROUND_DOWN, ROUND_CEILING, ROUND_FLOOR,
92 ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
93 ROUND_05UP
94]
Mark Dickinsonc69160e2010-05-04 14:35:33 +000095
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000096# Tests are built around these assumed context defaults.
97# test_main() restores the original context.
Stefan Krah1919b7e2012-03-21 18:25:23 +010098ORIGINAL_CONTEXT = {
99 C: C.getcontext().copy() if C else None,
100 P: P.getcontext().copy()
101}
102def init(m):
103 if not m: return
104 DefaultTestContext = m.Context(
Stefan Krah59a4a932013-01-16 12:58:59 +0100105 prec=9, rounding=ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100106 )
107 m.setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +0000108
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000109TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000110if __name__ == '__main__':
111 file = sys.argv[0]
112else:
113 file = __file__
114testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +0000115directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000116
Raymond Hettinger267b8682005-03-27 10:47:39 +0000117skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000118
119# Make sure it actually raises errors when not expected and caught in flags
120# Slower, since it runs some things several times.
121EXTENDEDERRORTEST = False
122
Stefan Krah1919b7e2012-03-21 18:25:23 +0100123# Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
124EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
125requires_extra_functionality = unittest.skipUnless(
126 EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
127skip_if_extra_functionality = unittest.skipIf(
128 EXTRA_FUNCTIONALITY, "test requires regular build")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000129
130
Stefan Krah1919b7e2012-03-21 18:25:23 +0100131class IBMTestCases(unittest.TestCase):
132 """Class which tests the Decimal class against the IBM test cases."""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000133
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000134 def setUp(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100135 self.context = self.decimal.Context()
136 self.readcontext = self.decimal.Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000137 self.ignore_list = ['#']
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000138
Stefan Krah1919b7e2012-03-21 18:25:23 +0100139 # List of individual .decTest test ids that correspond to tests that
140 # we're skipping for one reason or another.
141 self.skipped_test_ids = set([
142 # Skip implementation-specific scaleb tests.
143 'scbx164',
144 'scbx165',
145
146 # For some operations (currently exp, ln, log10, power), the decNumber
147 # reference implementation imposes additional restrictions on the context
148 # and operands. These restrictions are not part of the specification;
149 # however, the effect of these restrictions does show up in some of the
150 # testcases. We skip testcases that violate these restrictions, since
151 # Decimal behaves differently from decNumber for these testcases so these
152 # testcases would otherwise fail.
153 'expx901',
154 'expx902',
155 'expx903',
156 'expx905',
157 'lnx901',
158 'lnx902',
159 'lnx903',
160 'lnx905',
161 'logx901',
162 'logx902',
163 'logx903',
164 'logx905',
165 'powx1183',
166 'powx1184',
167 'powx4001',
168 'powx4002',
169 'powx4003',
170 'powx4005',
171 'powx4008',
172 'powx4010',
173 'powx4012',
174 'powx4014',
175 ])
176
177 if self.decimal == C:
178 # status has additional Subnormal, Underflow
179 self.skipped_test_ids.add('pwsx803')
180 self.skipped_test_ids.add('pwsx805')
181 # Correct rounding (skipped for decNumber, too)
182 self.skipped_test_ids.add('powx4302')
183 self.skipped_test_ids.add('powx4303')
184 self.skipped_test_ids.add('powx4342')
185 self.skipped_test_ids.add('powx4343')
186 # http://bugs.python.org/issue7049
187 self.skipped_test_ids.add('pwmx325')
188 self.skipped_test_ids.add('pwmx326')
189
190 # Map test directives to setter functions.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000191 self.ChangeDict = {'precision' : self.change_precision,
Stefan Krah1919b7e2012-03-21 18:25:23 +0100192 'rounding' : self.change_rounding_method,
193 'maxexponent' : self.change_max_exponent,
194 'minexponent' : self.change_min_exponent,
195 'clamp' : self.change_clamp}
196
197 # Name adapter to be able to change the Decimal and Context
198 # interface without changing the test files from Cowlishaw.
199 self.NameAdapter = {'and':'logical_and',
200 'apply':'_apply',
201 'class':'number_class',
202 'comparesig':'compare_signal',
203 'comparetotal':'compare_total',
204 'comparetotmag':'compare_total_mag',
205 'copy':'copy_decimal',
206 'copyabs':'copy_abs',
207 'copynegate':'copy_negate',
208 'copysign':'copy_sign',
209 'divideint':'divide_int',
210 'invert':'logical_invert',
211 'iscanonical':'is_canonical',
212 'isfinite':'is_finite',
213 'isinfinite':'is_infinite',
214 'isnan':'is_nan',
215 'isnormal':'is_normal',
216 'isqnan':'is_qnan',
217 'issigned':'is_signed',
218 'issnan':'is_snan',
219 'issubnormal':'is_subnormal',
220 'iszero':'is_zero',
221 'maxmag':'max_mag',
222 'minmag':'min_mag',
223 'nextminus':'next_minus',
224 'nextplus':'next_plus',
225 'nexttoward':'next_toward',
226 'or':'logical_or',
227 'reduce':'normalize',
228 'remaindernear':'remainder_near',
229 'samequantum':'same_quantum',
230 'squareroot':'sqrt',
231 'toeng':'to_eng_string',
232 'tointegral':'to_integral_value',
233 'tointegralx':'to_integral_exact',
234 'tosci':'to_sci_string',
235 'xor':'logical_xor'}
236
237 # Map test-case names to roundings.
Stefan Krah59a4a932013-01-16 12:58:59 +0100238 self.RoundingDict = {'ceiling' : ROUND_CEILING,
239 'down' : ROUND_DOWN,
240 'floor' : ROUND_FLOOR,
241 'half_down' : ROUND_HALF_DOWN,
242 'half_even' : ROUND_HALF_EVEN,
243 'half_up' : ROUND_HALF_UP,
244 'up' : ROUND_UP,
245 '05up' : ROUND_05UP}
Stefan Krah1919b7e2012-03-21 18:25:23 +0100246
247 # Map the test cases' error names to the actual errors.
248 self.ErrorNames = {'clamped' : self.decimal.Clamped,
249 'conversion_syntax' : self.decimal.InvalidOperation,
250 'division_by_zero' : self.decimal.DivisionByZero,
251 'division_impossible' : self.decimal.InvalidOperation,
252 'division_undefined' : self.decimal.InvalidOperation,
253 'inexact' : self.decimal.Inexact,
254 'invalid_context' : self.decimal.InvalidOperation,
255 'invalid_operation' : self.decimal.InvalidOperation,
256 'overflow' : self.decimal.Overflow,
257 'rounded' : self.decimal.Rounded,
258 'subnormal' : self.decimal.Subnormal,
259 'underflow' : self.decimal.Underflow}
260
261 # The following functions return True/False rather than a
262 # Decimal instance.
263 self.LogicalFunctions = ('is_canonical',
264 'is_finite',
265 'is_infinite',
266 'is_nan',
267 'is_normal',
268 'is_qnan',
269 'is_signed',
270 'is_snan',
271 'is_subnormal',
272 'is_zero',
273 'same_quantum')
274
275 def read_unlimited(self, v, context):
276 """Work around the limitations of the 32-bit _decimal version. The
277 guaranteed maximum values for prec, Emax etc. are 425000000,
278 but higher values usually work, except for rare corner cases.
279 In particular, all of the IBM tests pass with maximum values
280 of 1070000000."""
281 if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
282 self.readcontext._unsafe_setprec(1070000000)
283 self.readcontext._unsafe_setemax(1070000000)
284 self.readcontext._unsafe_setemin(-1070000000)
285 return self.readcontext.create_decimal(v)
286 else:
287 return self.decimal.Decimal(v, context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000288
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000289 def eval_file(self, file):
290 global skip_expected
291 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000292 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000293 return
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000294 with open(file) as f:
295 for line in f:
296 line = line.replace('\r\n', '').replace('\n', '')
297 #print line
298 try:
299 t = self.eval_line(line)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100300 except self.decimal.DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200301 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000302 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000303
304 return
305
306 def eval_line(self, s):
307 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
308 s = (s.split('->')[0] + '->' +
309 s.split('->')[1].split('--')[0]).strip()
310 else:
311 s = s.split('--')[0].strip()
312
313 for ignore in self.ignore_list:
314 if s.find(ignore) >= 0:
315 #print s.split()[0], 'NotImplemented--', ignore
316 return
317 if not s:
318 return
319 elif ':' in s:
320 return self.eval_directive(s)
321 else:
322 return self.eval_equation(s)
323
324 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000325 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000326 if funct == 'rounding':
Stefan Krah1919b7e2012-03-21 18:25:23 +0100327 value = self.RoundingDict[value]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000328 else:
329 try:
330 value = int(value)
331 except ValueError:
332 pass
333
Stefan Krah1919b7e2012-03-21 18:25:23 +0100334 funct = self.ChangeDict.get(funct, (lambda *args: None))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000335 funct(value)
336
337 def eval_equation(self, s):
Raymond Hettingered20ad82004-09-04 20:09:13 +0000338
339 if not TEST_ALL and random.random() < 0.90:
340 return
341
Stefan Krah1919b7e2012-03-21 18:25:23 +0100342 self.context.clear_flags()
343
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000344 try:
345 Sides = s.split('->')
346 L = Sides[0].strip().split()
347 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000348 if DEBUG:
349 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000350 funct = L[1].lower()
351 valstemp = L[2:]
352 L = Sides[1].strip().split()
353 ans = L[0]
354 exceptions = L[1:]
355 except (TypeError, AttributeError, IndexError):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100356 raise self.decimal.InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000357 def FixQuotes(val):
358 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
359 val = val.replace("'", '').replace('"', '')
360 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
361 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000362
Stefan Krah1919b7e2012-03-21 18:25:23 +0100363 if id in self.skipped_test_ids:
Mark Dickinson8a546532009-10-08 16:30:38 +0000364 return
365
Stefan Krah1919b7e2012-03-21 18:25:23 +0100366 fname = self.NameAdapter.get(funct, funct)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000367 if fname == 'rescale':
368 return
369 funct = getattr(self.context, fname)
370 vals = []
371 conglomerate = ''
372 quote = 0
Stefan Krah1919b7e2012-03-21 18:25:23 +0100373 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000374
Stefan Krah1919b7e2012-03-21 18:25:23 +0100375 for exception in Signals[self.decimal]:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000376 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000377 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000378 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000379 for i, val in enumerate(valstemp):
380 if val.count("'") % 2 == 1:
381 quote = 1 - quote
382 if quote:
383 conglomerate = conglomerate + ' ' + val
384 continue
385 else:
386 val = conglomerate + val
387 conglomerate = ''
388 v = FixQuotes(val)
389 if fname in ('to_sci_string', 'to_eng_string'):
390 if EXTENDEDERRORTEST:
391 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000392 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000393 try:
394 funct(self.context.create_decimal(v))
395 except error:
396 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100397 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000398 self.fail("Raised %s in %s when %s disabled" % \
399 (e, s, error))
400 else:
401 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000402 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000403 v = self.context.create_decimal(v)
404 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +0100405 v = self.read_unlimited(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000406 vals.append(v)
407
408 ans = FixQuotes(ans)
409
410 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
411 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000412 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000413 try:
414 funct(*vals)
415 except error:
416 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100417 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000418 self.fail("Raised %s in %s when %s disabled" % \
419 (e, s, error))
420 else:
421 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000422 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000423
424 # as above, but add traps cumulatively, to check precedence
Stefan Krah1919b7e2012-03-21 18:25:23 +0100425 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions]
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000426 for error in ordered_errors:
427 self.context.traps[error] = 1
428 try:
429 funct(*vals)
430 except error:
431 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100432 except Signals[self.decimal] as e:
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000433 self.fail("Raised %s in %s; expected %s" %
434 (type(e), s, error))
435 else:
436 self.fail("Did not raise %s in %s" % (error, s))
437 # reset traps
438 for error in ordered_errors:
439 self.context.traps[error] = 0
440
441
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000442 if DEBUG:
443 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000444 try:
445 result = str(funct(*vals))
Stefan Krah1919b7e2012-03-21 18:25:23 +0100446 if fname in self.LogicalFunctions:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000447 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Stefan Krah1919b7e2012-03-21 18:25:23 +0100448 except Signals[self.decimal] as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000449 self.fail("Raised %s in %s" % (error, s))
450 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000451 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000452 raise
453
454 myexceptions = self.getexceptions()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000455
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000456 myexceptions.sort(key=repr)
457 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000458
459 self.assertEqual(result, ans,
460 'Incorrect answer for ' + s + ' -- got ' + result)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100461
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000462 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000463 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000464 return
465
466 def getexceptions(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100467 return [e for e in Signals[self.decimal] if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000468
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000469 def change_precision(self, prec):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100470 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
471 self.context._unsafe_setprec(prec)
472 else:
473 self.context.prec = prec
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000474 def change_rounding_method(self, rounding):
475 self.context.rounding = rounding
476 def change_min_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100477 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
478 self.context._unsafe_setemin(exp)
479 else:
480 self.context.Emin = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000481 def change_max_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100482 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
483 self.context._unsafe_setemax(exp)
484 else:
485 self.context.Emax = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000486 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000487 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000488
Stefan Krah1919b7e2012-03-21 18:25:23 +0100489class CIBMTestCases(IBMTestCases):
490 decimal = C
491class PyIBMTestCases(IBMTestCases):
492 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000493
494# The following classes test the behaviour of Decimal according to PEP 327
495
Stefan Krah1919b7e2012-03-21 18:25:23 +0100496class ExplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000497 '''Unit tests for Explicit Construction cases of Decimal.'''
498
499 def test_explicit_empty(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100500 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000501 self.assertEqual(Decimal(), Decimal("0"))
502
503 def test_explicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100504 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000505 self.assertRaises(TypeError, Decimal, None)
506
507 def test_explicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100508 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000509
510 #positive
511 d = Decimal(45)
512 self.assertEqual(str(d), '45')
513
514 #very large positive
515 d = Decimal(500000123)
516 self.assertEqual(str(d), '500000123')
517
518 #negative
519 d = Decimal(-45)
520 self.assertEqual(str(d), '-45')
521
522 #zero
523 d = Decimal(0)
524 self.assertEqual(str(d), '0')
525
Stefan Krah1919b7e2012-03-21 18:25:23 +0100526 # single word longs
527 for n in range(0, 32):
528 for sign in (-1, 1):
529 for x in range(-5, 5):
530 i = sign * (2**n + x)
531 d = Decimal(i)
532 self.assertEqual(str(d), str(i))
533
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000534 def test_explicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100535 Decimal = self.decimal.Decimal
536 InvalidOperation = self.decimal.InvalidOperation
537 localcontext = self.decimal.localcontext
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000538
539 #empty
540 self.assertEqual(str(Decimal('')), 'NaN')
541
542 #int
543 self.assertEqual(str(Decimal('45')), '45')
544
545 #float
546 self.assertEqual(str(Decimal('45.34')), '45.34')
547
548 #engineer notation
549 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
550
551 #just not a number
552 self.assertEqual(str(Decimal('ugly')), 'NaN')
553
Christian Heimesa62da1d2008-01-12 19:39:10 +0000554 #leading and trailing whitespace permitted
555 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
556 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
Stefan Krah1919b7e2012-03-21 18:25:23 +0100557 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
558
559 # unicode whitespace
560 for lead in ["", ' ', '\u00a0', '\u205f']:
561 for trail in ["", ' ', '\u00a0', '\u205f']:
562 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
563 '9.311E+28')
564
565 with localcontext() as c:
566 c.traps[InvalidOperation] = True
567 # Invalid string
568 self.assertRaises(InvalidOperation, Decimal, "xyz")
569 # Two arguments max
570 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
571
572 # space within the numeric part
573 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
574 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
575
576 # unicode whitespace
577 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
578 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
579
580 # embedded NUL
581 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
582
Stefan Krah6e467042012-11-10 23:09:04 +0100583 @cpython_only
584 def test_from_legacy_strings(self):
585 import _testcapi
586 Decimal = self.decimal.Decimal
587 context = self.decimal.Context()
588
589 s = _testcapi.unicode_legacy_string('9.999999')
590 self.assertEqual(str(Decimal(s)), '9.999999')
591 self.assertEqual(str(context.create_decimal(s)), '9.999999')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000592
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000593 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100594 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000595
596 #zero
597 d = Decimal( (0, (0,), 0) )
598 self.assertEqual(str(d), '0')
599
600 #int
601 d = Decimal( (1, (4, 5), 0) )
602 self.assertEqual(str(d), '-45')
603
604 #float
605 d = Decimal( (0, (4, 5, 3, 4), -2) )
606 self.assertEqual(str(d), '45.34')
607
608 #weird
609 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
610 self.assertEqual(str(d), '-4.34913534E-17')
611
Stefan Krah1919b7e2012-03-21 18:25:23 +0100612 #inf
613 d = Decimal( (0, (), "F") )
614 self.assertEqual(str(d), 'Infinity')
615
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000616 #wrong number of items
617 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
618
619 #bad sign
620 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000621 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
622 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000623
624 #bad exp
625 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000626 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
627 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000628
629 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100630 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000631 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
632 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000633 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000634 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000635
Stefan Krah1919b7e2012-03-21 18:25:23 +0100636 def test_explicit_from_list(self):
637 Decimal = self.decimal.Decimal
638
639 d = Decimal([0, [0], 0])
640 self.assertEqual(str(d), '0')
641
642 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
643 self.assertEqual(str(d), '-4.34913534E-17')
644
645 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
646 self.assertEqual(str(d), '-4.34913534E-17')
647
648 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
649 self.assertEqual(str(d), '-4.34913534E-17')
650
Antoine Pitrou503ab332010-03-30 18:56:19 +0000651 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100652 Decimal = self.decimal.Decimal
653
Antoine Pitrou503ab332010-03-30 18:56:19 +0000654 self.assertIs(bool(Decimal(0)), False)
655 self.assertIs(bool(Decimal(1)), True)
656 self.assertEqual(Decimal(False), Decimal(0))
657 self.assertEqual(Decimal(True), Decimal(1))
658
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000659 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100660 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000661
662 #positive
663 d = Decimal(45)
664 e = Decimal(d)
665 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000666
667 #very large positive
668 d = Decimal(500000123)
669 e = Decimal(d)
670 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000671
672 #negative
673 d = Decimal(-45)
674 e = Decimal(d)
675 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000676
677 #zero
678 d = Decimal(0)
679 e = Decimal(d)
680 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000681
Raymond Hettinger96798592010-04-02 16:58:27 +0000682 @requires_IEEE_754
683 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100684
685 Decimal = self.decimal.Decimal
686
Raymond Hettinger96798592010-04-02 16:58:27 +0000687 r = Decimal(0.1)
688 self.assertEqual(type(r), Decimal)
689 self.assertEqual(str(r),
690 '0.1000000000000000055511151231257827021181583404541015625')
691 self.assertTrue(Decimal(float('nan')).is_qnan())
692 self.assertTrue(Decimal(float('inf')).is_infinite())
693 self.assertTrue(Decimal(float('-inf')).is_infinite())
694 self.assertEqual(str(Decimal(float('nan'))),
695 str(Decimal('NaN')))
696 self.assertEqual(str(Decimal(float('inf'))),
697 str(Decimal('Infinity')))
698 self.assertEqual(str(Decimal(float('-inf'))),
699 str(Decimal('-Infinity')))
700 self.assertEqual(str(Decimal(float('-0.0'))),
701 str(Decimal('-0')))
702 for i in range(200):
703 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
704 self.assertEqual(x, float(Decimal(x))) # roundtrip
705
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000706 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100707 Decimal = self.decimal.Decimal
708 InvalidOperation = self.decimal.InvalidOperation
709 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000710
Stefan Krah1919b7e2012-03-21 18:25:23 +0100711 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000712 nc.prec = 3
713
714 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000715 d = Decimal()
716 self.assertEqual(str(d), '0')
717 d = nc.create_decimal()
718 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000719
720 # from None
721 self.assertRaises(TypeError, nc.create_decimal, None)
722
723 # from int
724 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000725 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000726 self.assertEqual(nc.create_decimal(45678),
727 nc.create_decimal('457E+2'))
728
729 # from string
730 d = Decimal('456789')
731 self.assertEqual(str(d), '456789')
732 d = nc.create_decimal('456789')
733 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000734 # leading and trailing whitespace should result in a NaN;
735 # spaces are already checked in Cowlishaw's test-suite, so
736 # here we just check that a trailing newline results in a NaN
737 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000738
739 # from tuples
740 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
741 self.assertEqual(str(d), '-4.34913534E-17')
742 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
743 self.assertEqual(str(d), '-4.35E-17')
744
745 # from Decimal
746 prevdec = Decimal(500000123)
747 d = Decimal(prevdec)
748 self.assertEqual(str(d), '500000123')
749 d = nc.create_decimal(prevdec)
750 self.assertEqual(str(d), '5.00E+8')
751
Stefan Krah1919b7e2012-03-21 18:25:23 +0100752 # more integers
753 nc.prec = 28
754 nc.traps[InvalidOperation] = True
755
756 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
757 2**31-1, 2**31, 2**63-1, 2**63]:
758 d = nc.create_decimal(v)
759 self.assertTrue(isinstance(d, Decimal))
760 self.assertEqual(int(d), v)
761
762 nc.prec = 3
763 nc.traps[Rounded] = True
764 self.assertRaises(Rounded, nc.create_decimal, 1234)
765
766 # from string
767 nc.prec = 28
768 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
769 self.assertEqual(str(nc.create_decimal('45')), '45')
770 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
771 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
772
773 # invalid arguments
774 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
775 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
776 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
777
778 # too many NaN payload digits
779 nc.prec = 3
780 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
781 self.assertRaises(InvalidOperation, nc.create_decimal,
782 Decimal('NaN12345'))
783
784 nc.traps[InvalidOperation] = False
785 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
786 self.assertTrue(nc.flags[InvalidOperation])
787
788 nc.flags[InvalidOperation] = False
789 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
790 self.assertTrue(nc.flags[InvalidOperation])
791
792 def test_explicit_context_create_from_float(self):
793
794 Decimal = self.decimal.Decimal
795
796 nc = self.decimal.Context()
797 r = nc.create_decimal(0.1)
798 self.assertEqual(type(r), Decimal)
799 self.assertEqual(str(r), '0.1000000000000000055511151231')
800 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
801 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
802 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
803 self.assertEqual(str(nc.create_decimal(float('nan'))),
804 str(nc.create_decimal('NaN')))
805 self.assertEqual(str(nc.create_decimal(float('inf'))),
806 str(nc.create_decimal('Infinity')))
807 self.assertEqual(str(nc.create_decimal(float('-inf'))),
808 str(nc.create_decimal('-Infinity')))
809 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
810 str(nc.create_decimal('-0')))
811 nc.prec = 100
812 for i in range(200):
813 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
814 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
815
Mark Dickinson345adc42009-08-02 10:14:23 +0000816 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100817 Decimal = self.decimal.Decimal
818
Mark Dickinson345adc42009-08-02 10:14:23 +0000819 test_values = {
820 '\uff11': '1',
821 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
822 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
823 }
824 for input, expected in test_values.items():
825 self.assertEqual(str(Decimal(input)), expected)
826
Stefan Krah1919b7e2012-03-21 18:25:23 +0100827class CExplicitConstructionTest(ExplicitConstructionTest):
828 decimal = C
829class PyExplicitConstructionTest(ExplicitConstructionTest):
830 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000831
Stefan Krah1919b7e2012-03-21 18:25:23 +0100832class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000833 '''Unit tests for Implicit Construction cases of Decimal.'''
834
835 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100836 Decimal = self.decimal.Decimal
837 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000838
839 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100840 Decimal = self.decimal.Decimal
841
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000842 #normal
843 self.assertEqual(str(Decimal(5) + 45), '50')
844 #exceeding precision
845 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
846
847 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100848 Decimal = self.decimal.Decimal
849 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000850
851 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100852 Decimal = self.decimal.Decimal
853 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000854
855 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100856 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000857 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
858
Raymond Hettinger267b8682005-03-27 10:47:39 +0000859 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100860 Decimal = self.decimal.Decimal
861
Raymond Hettinger267b8682005-03-27 10:47:39 +0000862 # Allow other classes to be trained to interact with Decimals
863 class E:
864 def __divmod__(self, other):
865 return 'divmod ' + str(other)
866 def __rdivmod__(self, other):
867 return str(other) + ' rdivmod'
868 def __lt__(self, other):
869 return 'lt ' + str(other)
870 def __gt__(self, other):
871 return 'gt ' + str(other)
872 def __le__(self, other):
873 return 'le ' + str(other)
874 def __ge__(self, other):
875 return 'ge ' + str(other)
876 def __eq__(self, other):
877 return 'eq ' + str(other)
878 def __ne__(self, other):
879 return 'ne ' + str(other)
880
881 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
882 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
883 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
884 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
885 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
886 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
887 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
888 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
889
890 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000891 oplist = [
892 ('+', '__add__', '__radd__'),
893 ('-', '__sub__', '__rsub__'),
894 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000895 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000896 ('%', '__mod__', '__rmod__'),
897 ('//', '__floordiv__', '__rfloordiv__'),
898 ('**', '__pow__', '__rpow__')
899 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000900
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000901 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000902 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
903 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
904 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
905 'str' + lop + '10')
906 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
907 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000908
Stefan Krah1919b7e2012-03-21 18:25:23 +0100909class CImplicitConstructionTest(ImplicitConstructionTest):
910 decimal = C
911class PyImplicitConstructionTest(ImplicitConstructionTest):
912 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000913
Stefan Krah1919b7e2012-03-21 18:25:23 +0100914class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000915 '''Unit tests for the format function.'''
916 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100917 Decimal = self.decimal.Decimal
918
Christian Heimesf16baeb2008-02-29 14:57:44 +0000919 # triples giving a format, a Decimal, and the expected result
920 test_values = [
921 ('e', '0E-15', '0e-15'),
922 ('e', '2.3E-15', '2.3e-15'),
923 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
924 ('e', '2.30000E-15', '2.30000e-15'),
925 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
926 ('e', '1.5', '1.5e+0'),
927 ('e', '0.15', '1.5e-1'),
928 ('e', '0.015', '1.5e-2'),
929 ('e', '0.0000000000015', '1.5e-12'),
930 ('e', '15.0', '1.50e+1'),
931 ('e', '-15', '-1.5e+1'),
932 ('e', '0', '0e+0'),
933 ('e', '0E1', '0e+1'),
934 ('e', '0.0', '0e-1'),
935 ('e', '0.00', '0e-2'),
936 ('.6e', '0E-15', '0.000000e-9'),
937 ('.6e', '0', '0.000000e+6'),
938 ('.6e', '9.999999', '9.999999e+0'),
939 ('.6e', '9.9999999', '1.000000e+1'),
940 ('.6e', '-1.23e5', '-1.230000e+5'),
941 ('.6e', '1.23456789e-3', '1.234568e-3'),
942 ('f', '0', '0'),
943 ('f', '0.0', '0.0'),
944 ('f', '0E-2', '0.00'),
945 ('f', '0.00E-8', '0.0000000000'),
946 ('f', '0E1', '0'), # loses exponent information
947 ('f', '3.2E1', '32'),
948 ('f', '3.2E2', '320'),
949 ('f', '3.20E2', '320'),
950 ('f', '3.200E2', '320.0'),
951 ('f', '3.2E-6', '0.0000032'),
952 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
953 ('.6f', '0E1', '0.000000'),
954 ('.6f', '0', '0.000000'),
955 ('.0f', '0', '0'), # no decimal point
956 ('.0f', '0e-2', '0'),
957 ('.0f', '3.14159265', '3'),
958 ('.1f', '3.14159265', '3.1'),
959 ('.4f', '3.14159265', '3.1416'),
960 ('.6f', '3.14159265', '3.141593'),
961 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
962 ('.8f', '3.14159265', '3.14159265'),
963 ('.9f', '3.14159265', '3.141592650'),
964
965 ('g', '0', '0'),
966 ('g', '0.0', '0.0'),
967 ('g', '0E1', '0e+1'),
968 ('G', '0E1', '0E+1'),
969 ('g', '0E-5', '0.00000'),
970 ('g', '0E-6', '0.000000'),
971 ('g', '0E-7', '0e-7'),
972 ('g', '-0E2', '-0e+2'),
973 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100974 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000975 ('.1g', '3.14159265', '3'),
976 ('.2g', '3.14159265', '3.1'),
977 ('.5g', '3.14159265', '3.1416'),
978 ('.7g', '3.14159265', '3.141593'),
979 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
980 ('.9g', '3.14159265', '3.14159265'),
981 ('.10g', '3.14159265', '3.14159265'), # don't pad
982
983 ('%', '0E1', '0%'),
984 ('%', '0E0', '0%'),
985 ('%', '0E-1', '0%'),
986 ('%', '0E-2', '0%'),
987 ('%', '0E-3', '0.0%'),
988 ('%', '0E-4', '0.00%'),
989
990 ('.3%', '0', '0.000%'), # all zeros treated equally
991 ('.3%', '0E10', '0.000%'),
992 ('.3%', '0E-10', '0.000%'),
993 ('.3%', '2.34', '234.000%'),
994 ('.3%', '1.234567', '123.457%'),
995 ('.0%', '1.23', '123%'),
996
997 ('e', 'NaN', 'NaN'),
998 ('f', '-NaN123', '-NaN123'),
999 ('+g', 'NaN456', '+NaN456'),
1000 ('.3e', 'Inf', 'Infinity'),
1001 ('.16f', '-Inf', '-Infinity'),
1002 ('.0g', '-sNaN', '-sNaN'),
1003
1004 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001005
Mark Dickinson79f52032009-03-17 23:12:51 +00001006 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001007 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001008 ('<6', '123', '123 '),
1009 ('>6', '123', ' 123'),
1010 ('^6', '123', ' 123 '),
1011 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001012 ('#<10', 'NaN', 'NaN#######'),
1013 ('#<10', '-4.3', '-4.3######'),
1014 ('#<+10', '0.0130', '+0.0130###'),
1015 ('#< 10', '0.0130', ' 0.0130###'),
1016 ('@>10', '-Inf', '@-Infinity'),
1017 ('#>5', '-Inf', '-Infinity'),
1018 ('?^5', '123', '?123?'),
1019 ('%^6', '123', '%123%%'),
1020 (' ^6', '-45.6', '-45.6 '),
1021 ('/=10', '-45.6', '-/////45.6'),
1022 ('/=+10', '45.6', '+/////45.6'),
1023 ('/= 10', '45.6', ' /////45.6'),
Stefan Krah6edda142013-05-29 15:45:38 +02001024 ('\x00=10', '-inf', '-\x00Infinity'),
1025 ('\x00^16', '-inf', '\x00\x00\x00-Infinity\x00\x00\x00\x00'),
1026 ('\x00>10', '1.2345', '\x00\x00\x00\x001.2345'),
1027 ('\x00<10', '1.2345', '1.2345\x00\x00\x00\x00'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001028
1029 # thousands separator
1030 (',', '1234567', '1,234,567'),
1031 (',', '123456', '123,456'),
1032 (',', '12345', '12,345'),
1033 (',', '1234', '1,234'),
1034 (',', '123', '123'),
1035 (',', '12', '12'),
1036 (',', '1', '1'),
1037 (',', '0', '0'),
1038 (',', '-1234567', '-1,234,567'),
1039 (',', '-123456', '-123,456'),
1040 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001041 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001042 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1043 ('+08,', '123456', '+123,456'), # but not if there's a sign
1044 (' 08,', '123456', ' 123,456'),
1045 ('08,', '-123456', '-123,456'),
1046 ('+09,', '123456', '+0,123,456'),
1047 # ... with fractional part...
1048 ('07,', '1234.56', '1,234.56'),
1049 ('08,', '1234.56', '1,234.56'),
1050 ('09,', '1234.56', '01,234.56'),
1051 ('010,', '1234.56', '001,234.56'),
1052 ('011,', '1234.56', '0,001,234.56'),
1053 ('012,', '1234.56', '0,001,234.56'),
1054 ('08,.1f', '1234.5', '01,234.5'),
1055 # no thousands separators in fraction part
1056 (',', '1.23456789', '1.23456789'),
1057 (',%', '123.456789', '12,345.6789%'),
1058 (',e', '123456', '1.23456e+5'),
1059 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001060
1061 # issue 6850
1062 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001063 ]
1064 for fmt, d, result in test_values:
1065 self.assertEqual(format(Decimal(d), fmt), result)
1066
Stefan Krah1919b7e2012-03-21 18:25:23 +01001067 # bytes format argument
1068 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1069
Mark Dickinson79f52032009-03-17 23:12:51 +00001070 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001071 Decimal = self.decimal.Decimal
1072
Mark Dickinson79f52032009-03-17 23:12:51 +00001073 try:
1074 from locale import CHAR_MAX
1075 except ImportError:
1076 return
1077
Stefan Krah1919b7e2012-03-21 18:25:23 +01001078 def make_grouping(lst):
1079 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1080
1081 def get_fmt(x, override=None, fmt='n'):
1082 if self.decimal == C:
1083 return Decimal(x).__format__(fmt, override)
1084 else:
1085 return Decimal(x).__format__(fmt, _localeconv=override)
1086
Mark Dickinson79f52032009-03-17 23:12:51 +00001087 # Set up some localeconv-like dictionaries
1088 en_US = {
1089 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001090 'grouping' : make_grouping([3, 3, 0]),
1091 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001092 }
1093
1094 fr_FR = {
1095 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001096 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001097 'thousands_sep' : ''
1098 }
1099
1100 ru_RU = {
1101 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001102 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001103 'thousands_sep' : ' '
1104 }
1105
1106 crazy = {
1107 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001108 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001109 'thousands_sep' : '-'
1110 }
1111
Stefan Krah1919b7e2012-03-21 18:25:23 +01001112 dotsep_wide = {
1113 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1114 'grouping': make_grouping([3, 3, 0]),
1115 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1116 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001117
1118 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1119 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1120 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1121 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1122
1123 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1124 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1125 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1126 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1127
1128 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1129 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1130 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1131 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1132
Mark Dickinson7303b592009-03-18 08:25:36 +00001133 # zero padding
1134 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1135 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1136 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1137 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1138
1139 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1140 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1141 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1142 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1143 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1144 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1145
1146 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1147 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1148 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1149 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1150 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1151 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1152 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1153 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1154
Stefan Krah1919b7e2012-03-21 18:25:23 +01001155 # wide char separator and decimal point
1156 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1157 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001158
Stefan Krah6fb204a2012-09-28 16:18:54 +02001159 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001160 def test_wide_char_separator_decimal_point(self):
1161 # locale with wide char separator and decimal point
Stefan Krah8a491a82012-09-28 17:17:11 +02001162 import locale
Stefan Krah1919b7e2012-03-21 18:25:23 +01001163 Decimal = self.decimal.Decimal
1164
Stefan Krah8a491a82012-09-28 17:17:11 +02001165 decimal_point = locale.localeconv()['decimal_point']
1166 thousands_sep = locale.localeconv()['thousands_sep']
1167 if decimal_point != '\u066b' or thousands_sep != '\u066c':
1168 return
1169
Stefan Krah1919b7e2012-03-21 18:25:23 +01001170 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1171 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001172
1173class CFormatTest(FormatTest):
1174 decimal = C
1175class PyFormatTest(FormatTest):
1176 decimal = P
1177
1178class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001179 '''Unit tests for all arithmetic operators, binary and unary.'''
1180
1181 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001182 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001183
1184 d1 = Decimal('-11.1')
1185 d2 = Decimal('22.2')
1186
1187 #two Decimals
1188 self.assertEqual(d1+d2, Decimal('11.1'))
1189 self.assertEqual(d2+d1, Decimal('11.1'))
1190
1191 #with other type, left
1192 c = d1 + 5
1193 self.assertEqual(c, Decimal('-6.1'))
1194 self.assertEqual(type(c), type(d1))
1195
1196 #with other type, right
1197 c = 5 + d1
1198 self.assertEqual(c, Decimal('-6.1'))
1199 self.assertEqual(type(c), type(d1))
1200
1201 #inline with decimal
1202 d1 += d2
1203 self.assertEqual(d1, Decimal('11.1'))
1204
1205 #inline with other type
1206 d1 += 5
1207 self.assertEqual(d1, Decimal('16.1'))
1208
1209 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001210 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001211
1212 d1 = Decimal('-11.1')
1213 d2 = Decimal('22.2')
1214
1215 #two Decimals
1216 self.assertEqual(d1-d2, Decimal('-33.3'))
1217 self.assertEqual(d2-d1, Decimal('33.3'))
1218
1219 #with other type, left
1220 c = d1 - 5
1221 self.assertEqual(c, Decimal('-16.1'))
1222 self.assertEqual(type(c), type(d1))
1223
1224 #with other type, right
1225 c = 5 - d1
1226 self.assertEqual(c, Decimal('16.1'))
1227 self.assertEqual(type(c), type(d1))
1228
1229 #inline with decimal
1230 d1 -= d2
1231 self.assertEqual(d1, Decimal('-33.3'))
1232
1233 #inline with other type
1234 d1 -= 5
1235 self.assertEqual(d1, Decimal('-38.3'))
1236
1237 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001238 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001239
1240 d1 = Decimal('-5')
1241 d2 = Decimal('3')
1242
1243 #two Decimals
1244 self.assertEqual(d1*d2, Decimal('-15'))
1245 self.assertEqual(d2*d1, Decimal('-15'))
1246
1247 #with other type, left
1248 c = d1 * 5
1249 self.assertEqual(c, Decimal('-25'))
1250 self.assertEqual(type(c), type(d1))
1251
1252 #with other type, right
1253 c = 5 * d1
1254 self.assertEqual(c, Decimal('-25'))
1255 self.assertEqual(type(c), type(d1))
1256
1257 #inline with decimal
1258 d1 *= d2
1259 self.assertEqual(d1, Decimal('-15'))
1260
1261 #inline with other type
1262 d1 *= 5
1263 self.assertEqual(d1, Decimal('-75'))
1264
1265 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001266 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001267
1268 d1 = Decimal('-5')
1269 d2 = Decimal('2')
1270
1271 #two Decimals
1272 self.assertEqual(d1/d2, Decimal('-2.5'))
1273 self.assertEqual(d2/d1, Decimal('-0.4'))
1274
1275 #with other type, left
1276 c = d1 / 4
1277 self.assertEqual(c, Decimal('-1.25'))
1278 self.assertEqual(type(c), type(d1))
1279
1280 #with other type, right
1281 c = 4 / d1
1282 self.assertEqual(c, Decimal('-0.8'))
1283 self.assertEqual(type(c), type(d1))
1284
1285 #inline with decimal
1286 d1 /= d2
1287 self.assertEqual(d1, Decimal('-2.5'))
1288
1289 #inline with other type
1290 d1 /= 4
1291 self.assertEqual(d1, Decimal('-0.625'))
1292
1293 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001294 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001295
1296 d1 = Decimal('5')
1297 d2 = Decimal('2')
1298
1299 #two Decimals
1300 self.assertEqual(d1//d2, Decimal('2'))
1301 self.assertEqual(d2//d1, Decimal('0'))
1302
1303 #with other type, left
1304 c = d1 // 4
1305 self.assertEqual(c, Decimal('1'))
1306 self.assertEqual(type(c), type(d1))
1307
1308 #with other type, right
1309 c = 7 // d1
1310 self.assertEqual(c, Decimal('1'))
1311 self.assertEqual(type(c), type(d1))
1312
1313 #inline with decimal
1314 d1 //= d2
1315 self.assertEqual(d1, Decimal('2'))
1316
1317 #inline with other type
1318 d1 //= 2
1319 self.assertEqual(d1, Decimal('1'))
1320
1321 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001322 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001323
1324 d1 = Decimal('5')
1325 d2 = Decimal('2')
1326
1327 #two Decimals
1328 self.assertEqual(d1**d2, Decimal('25'))
1329 self.assertEqual(d2**d1, Decimal('32'))
1330
1331 #with other type, left
1332 c = d1 ** 4
1333 self.assertEqual(c, Decimal('625'))
1334 self.assertEqual(type(c), type(d1))
1335
1336 #with other type, right
1337 c = 7 ** d1
1338 self.assertEqual(c, Decimal('16807'))
1339 self.assertEqual(type(c), type(d1))
1340
1341 #inline with decimal
1342 d1 **= d2
1343 self.assertEqual(d1, Decimal('25'))
1344
1345 #inline with other type
1346 d1 **= 4
1347 self.assertEqual(d1, Decimal('390625'))
1348
1349 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001350 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001351
1352 d1 = Decimal('5')
1353 d2 = Decimal('2')
1354
1355 #two Decimals
1356 self.assertEqual(d1%d2, Decimal('1'))
1357 self.assertEqual(d2%d1, Decimal('2'))
1358
1359 #with other type, left
1360 c = d1 % 4
1361 self.assertEqual(c, Decimal('1'))
1362 self.assertEqual(type(c), type(d1))
1363
1364 #with other type, right
1365 c = 7 % d1
1366 self.assertEqual(c, Decimal('2'))
1367 self.assertEqual(type(c), type(d1))
1368
1369 #inline with decimal
1370 d1 %= d2
1371 self.assertEqual(d1, Decimal('1'))
1372
1373 #inline with other type
1374 d1 %= 4
1375 self.assertEqual(d1, Decimal('1'))
1376
1377 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001378 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001379
1380 d1 = Decimal('5')
1381 d2 = Decimal('2')
1382
1383 #two Decimals
1384 (p, q) = divmod(d1, d2)
1385 self.assertEqual(p, Decimal('2'))
1386 self.assertEqual(q, Decimal('1'))
1387 self.assertEqual(type(p), type(d1))
1388 self.assertEqual(type(q), type(d1))
1389
1390 #with other type, left
1391 (p, q) = divmod(d1, 4)
1392 self.assertEqual(p, Decimal('1'))
1393 self.assertEqual(q, Decimal('1'))
1394 self.assertEqual(type(p), type(d1))
1395 self.assertEqual(type(q), type(d1))
1396
1397 #with other type, right
1398 (p, q) = divmod(7, d1)
1399 self.assertEqual(p, Decimal('1'))
1400 self.assertEqual(q, Decimal('2'))
1401 self.assertEqual(type(p), type(d1))
1402 self.assertEqual(type(q), type(d1))
1403
1404 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001405 Decimal = self.decimal.Decimal
1406
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001407 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1408 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1409 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1410
Christian Heimes77c02eb2008-02-09 02:18:51 +00001411 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001412 # comparisons involving signaling nans signal InvalidOperation
1413
1414 # order comparisons (<, <=, >, >=) involving only quiet nans
1415 # also signal InvalidOperation
1416
1417 # equality comparisons (==, !=) involving only quiet nans
1418 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001419 Decimal = self.decimal.Decimal
1420 InvalidOperation = self.decimal.InvalidOperation
1421 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001422
Christian Heimes77c02eb2008-02-09 02:18:51 +00001423 n = Decimal('NaN')
1424 s = Decimal('sNaN')
1425 i = Decimal('Inf')
1426 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001427
1428 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1429 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1430 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1431 equality_ops = operator.eq, operator.ne
1432
1433 # results when InvalidOperation is not trapped
1434 for x, y in qnan_pairs + snan_pairs:
1435 for op in order_ops + equality_ops:
1436 got = op(x, y)
1437 expected = True if op is operator.ne else False
1438 self.assertIs(expected, got,
1439 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1440 "got {4!r}".format(
1441 expected, op.__name__, x, y, got))
1442
1443 # repeat the above, but this time trap the InvalidOperation
1444 with localcontext() as ctx:
1445 ctx.traps[InvalidOperation] = 1
1446
1447 for x, y in qnan_pairs:
1448 for op in equality_ops:
1449 got = op(x, y)
1450 expected = True if op is operator.ne else False
1451 self.assertIs(expected, got,
1452 "expected {0!r} for "
1453 "operator.{1}({2!r}, {3!r}); "
1454 "got {4!r}".format(
1455 expected, op.__name__, x, y, got))
1456
1457 for x, y in snan_pairs:
1458 for op in equality_ops:
1459 self.assertRaises(InvalidOperation, operator.eq, x, y)
1460 self.assertRaises(InvalidOperation, operator.ne, x, y)
1461
1462 for x, y in qnan_pairs + snan_pairs:
1463 for op in order_ops:
1464 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001465
Mark Dickinson84230a12010-02-18 14:49:50 +00001466 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001467 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001468
Stefan Krah1919b7e2012-03-21 18:25:23 +01001469 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001470 self.assertEqual(Decimal(1).copy_sign(-2), d)
1471 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1472
Stefan Krah1919b7e2012-03-21 18:25:23 +01001473class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1474 decimal = C
1475class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1476 decimal = P
1477
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001478# The following are two functions used to test threading in the next class
1479
1480def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001481 Decimal = cls.decimal.Decimal
1482 InvalidOperation = cls.decimal.InvalidOperation
1483 DivisionByZero = cls.decimal.DivisionByZero
1484 Overflow = cls.decimal.Overflow
1485 Underflow = cls.decimal.Underflow
1486 Inexact = cls.decimal.Inexact
1487 getcontext = cls.decimal.getcontext
1488 localcontext = cls.decimal.localcontext
1489
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001490 d1 = Decimal(1)
1491 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001492 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001493
Stefan Krah1919b7e2012-03-21 18:25:23 +01001494 cls.finish1.set()
1495 cls.synchro.wait()
1496
1497 test2 = d1/d3
1498 with localcontext() as c2:
1499 cls.assertTrue(c2.flags[Inexact])
1500 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1501 cls.assertTrue(c2.flags[DivisionByZero])
1502 with localcontext() as c3:
1503 cls.assertTrue(c3.flags[Inexact])
1504 cls.assertTrue(c3.flags[DivisionByZero])
1505 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1506 cls.assertTrue(c3.flags[InvalidOperation])
1507 del c3
1508 cls.assertFalse(c2.flags[InvalidOperation])
1509 del c2
1510
1511 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1512 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1513
1514 c1 = getcontext()
1515 cls.assertTrue(c1.flags[Inexact])
1516 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1517 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001518 return
1519
1520def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001521 Decimal = cls.decimal.Decimal
1522 InvalidOperation = cls.decimal.InvalidOperation
1523 DivisionByZero = cls.decimal.DivisionByZero
1524 Overflow = cls.decimal.Overflow
1525 Underflow = cls.decimal.Underflow
1526 Inexact = cls.decimal.Inexact
1527 getcontext = cls.decimal.getcontext
1528 localcontext = cls.decimal.localcontext
1529
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001530 d1 = Decimal(1)
1531 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001532 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001533
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001534 thiscontext = getcontext()
1535 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001536 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001537
1538 with localcontext() as c2:
1539 cls.assertTrue(c2.flags[Inexact])
1540 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1541 cls.assertTrue(c2.flags[Overflow])
1542 with localcontext(thiscontext) as c3:
1543 cls.assertTrue(c3.flags[Inexact])
1544 cls.assertFalse(c3.flags[Overflow])
1545 c3.traps[Underflow] = True
1546 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1547 cls.assertTrue(c3.flags[Underflow])
1548 del c3
1549 cls.assertFalse(c2.flags[Underflow])
1550 cls.assertFalse(c2.traps[Underflow])
1551 del c2
1552
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001553 cls.synchro.set()
1554 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001555
Stefan Krah1919b7e2012-03-21 18:25:23 +01001556 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001557 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001558
1559 cls.assertFalse(thiscontext.traps[Underflow])
1560 cls.assertTrue(thiscontext.flags[Inexact])
1561 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1562 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001563 return
1564
Stefan Krah1919b7e2012-03-21 18:25:23 +01001565class ThreadingTest(unittest.TestCase):
1566 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001567
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001568 # Take care executing this test from IDLE, there's an issue in threading
1569 # that hangs IDLE and I couldn't find it
1570
1571 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001572 DefaultContext = self.decimal.DefaultContext
1573
1574 if self.decimal == C and not self.decimal.HAVE_THREADS:
1575 self.skipTest("compiled without threading")
1576 # Test the "threading isolation" of a Context. Also test changing
1577 # the DefaultContext, which acts as a template for the thread-local
1578 # contexts.
1579 save_prec = DefaultContext.prec
1580 save_emax = DefaultContext.Emax
1581 save_emin = DefaultContext.Emin
1582 DefaultContext.prec = 24
1583 DefaultContext.Emax = 425000000
1584 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001585
1586 self.synchro = threading.Event()
1587 self.finish1 = threading.Event()
1588 self.finish2 = threading.Event()
1589
1590 th1 = threading.Thread(target=thfunc1, args=(self,))
1591 th2 = threading.Thread(target=thfunc2, args=(self,))
1592
1593 th1.start()
1594 th2.start()
1595
1596 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001597 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001598
1599 for sig in Signals[self.decimal]:
1600 self.assertFalse(DefaultContext.flags[sig])
1601
1602 DefaultContext.prec = save_prec
1603 DefaultContext.Emax = save_emax
1604 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001605 return
1606
Stefan Krah1919b7e2012-03-21 18:25:23 +01001607@unittest.skipUnless(threading, 'threading required')
1608class CThreadingTest(ThreadingTest):
1609 decimal = C
1610@unittest.skipUnless(threading, 'threading required')
1611class PyThreadingTest(ThreadingTest):
1612 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001613
Stefan Krah1919b7e2012-03-21 18:25:23 +01001614class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001615 '''Unit tests for Usability cases of Decimal.'''
1616
1617 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001618
Stefan Krah1919b7e2012-03-21 18:25:23 +01001619 Decimal = self.decimal.Decimal
1620
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001621 da = Decimal('23.42')
1622 db = Decimal('23.42')
1623 dc = Decimal('45')
1624
1625 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001626 self.assertGreater(dc, da)
1627 self.assertGreaterEqual(dc, da)
1628 self.assertLess(da, dc)
1629 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001630 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001631 self.assertNotEqual(da, dc)
1632 self.assertLessEqual(da, db)
1633 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001634
1635 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001636 self.assertGreater(dc, 23)
1637 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001638 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001639
1640 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001641 self.assertNotEqual(da, 'ugly')
1642 self.assertNotEqual(da, 32.7)
1643 self.assertNotEqual(da, object())
1644 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001645
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001646 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001647 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001648 b = a[:]
1649 random.shuffle(a)
1650 a.sort()
1651 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001652
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001653 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001654 Decimal = self.decimal.Decimal
1655
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001656 da = Decimal('0.25')
1657 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001658 self.assertLess(da, 3.0)
1659 self.assertLessEqual(da, 3.0)
1660 self.assertGreater(db, 0.25)
1661 self.assertGreaterEqual(db, 0.25)
1662 self.assertNotEqual(da, 1.5)
1663 self.assertEqual(da, 0.25)
1664 self.assertGreater(3.0, da)
1665 self.assertGreaterEqual(3.0, da)
1666 self.assertLess(0.25, db)
1667 self.assertLessEqual(0.25, db)
1668 self.assertNotEqual(0.25, db)
1669 self.assertEqual(3.0, db)
1670 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001671
Stefan Krah1919b7e2012-03-21 18:25:23 +01001672 def test_decimal_complex_comparison(self):
1673 Decimal = self.decimal.Decimal
1674
1675 da = Decimal('0.25')
1676 db = Decimal('3.0')
1677 self.assertNotEqual(da, (1.5+0j))
1678 self.assertNotEqual((1.5+0j), da)
1679 self.assertEqual(da, (0.25+0j))
1680 self.assertEqual((0.25+0j), da)
1681 self.assertEqual((3.0+0j), db)
1682 self.assertEqual(db, (3.0+0j))
1683
1684 self.assertNotEqual(db, (3.0+1j))
1685 self.assertNotEqual((3.0+1j), db)
1686
1687 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1688 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1689 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1690 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1691
1692 def test_decimal_fraction_comparison(self):
1693 D = self.decimal.Decimal
1694 F = fractions[self.decimal].Fraction
1695 Context = self.decimal.Context
1696 localcontext = self.decimal.localcontext
1697 InvalidOperation = self.decimal.InvalidOperation
1698
1699
1700 emax = C.MAX_EMAX if C else 999999999
1701 emin = C.MIN_EMIN if C else -999999999
1702 etiny = C.MIN_ETINY if C else -1999999997
1703 c = Context(Emax=emax, Emin=emin)
1704
1705 with localcontext(c):
1706 c.prec = emax
1707 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1708 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1709 self.assertLess(F(0,1), D("1e" + str(etiny)))
1710 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1711 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1712 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1713
1714 self.assertEqual(D("0.1"), F(1,10))
1715 self.assertEqual(F(1,10), D("0.1"))
1716
1717 c.prec = 300
1718 self.assertNotEqual(D(1)/3, F(1,3))
1719 self.assertNotEqual(F(1,3), D(1)/3)
1720
1721 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1722 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1723
1724 self.assertGreater(D('inf'), F(99999999999,123))
1725 self.assertGreater(D('inf'), F(-99999999999,123))
1726 self.assertLess(D('-inf'), F(99999999999,123))
1727 self.assertLess(D('-inf'), F(-99999999999,123))
1728
1729 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1730 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1731 self.assertNotEqual(D('nan'), F(-9,123))
1732 self.assertNotEqual(F(-9,123), D('nan'))
1733
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001734 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001735 Decimal = self.decimal.Decimal
1736
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001737 d = Decimal('43.24')
1738 c = copy.copy(d)
1739 self.assertEqual(id(c), id(d))
1740 dc = copy.deepcopy(d)
1741 self.assertEqual(id(dc), id(d))
1742
1743 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001744
1745 Decimal = self.decimal.Decimal
1746 localcontext = self.decimal.localcontext
1747
Stefan Krahdc817b22010-11-17 11:16:34 +00001748 def hashit(d):
1749 a = hash(d)
1750 b = d.__hash__()
1751 self.assertEqual(a, b)
1752 return a
1753
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001754 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001755 hashit(Decimal(23))
1756 hashit(Decimal('Infinity'))
1757 hashit(Decimal('-Infinity'))
1758 hashit(Decimal('nan123'))
1759 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001760
1761 test_values = [Decimal(sign*(2**m + n))
1762 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001763 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001764 for n in range(-10, 10)
1765 for sign in [-1, 1]]
1766 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001767 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001768 Decimal("-0"), # zeros
1769 Decimal("0.00"),
1770 Decimal("-0.000"),
1771 Decimal("0E10"),
1772 Decimal("-0E12"),
1773 Decimal("10.0"), # negative exponent
1774 Decimal("-23.00000"),
1775 Decimal("1230E100"), # positive exponent
1776 Decimal("-4.5678E50"),
1777 # a value for which hash(n) != hash(n % (2**64-1))
1778 # in Python pre-2.6
1779 Decimal(2**64 + 2**32 - 1),
1780 # selection of values which fail with the old (before
1781 # version 2.6) long.__hash__
1782 Decimal("1.634E100"),
1783 Decimal("90.697E100"),
1784 Decimal("188.83E100"),
1785 Decimal("1652.9E100"),
1786 Decimal("56531E100"),
1787 ])
1788
1789 # check that hash(d) == hash(int(d)) for integral values
1790 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001791 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001792
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001793 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001794 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001795 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001796 self.assertTrue(hashit(Decimal('Inf')))
1797 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001798
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001799 # check that the hashes of a Decimal float match when they
1800 # represent exactly the same values
1801 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1802 '34.0', '2.5', '112390.625', '-0.515625']
1803 for s in test_strings:
1804 f = float(s)
1805 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001806 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001807
Stefan Krah1919b7e2012-03-21 18:25:23 +01001808 with localcontext() as c:
1809 # check that the value of the hash doesn't depend on the
1810 # current context (issue #1757)
1811 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001812
Stefan Krah1919b7e2012-03-21 18:25:23 +01001813 c.prec = 6
1814 h1 = hashit(x)
1815 c.prec = 10
1816 h2 = hashit(x)
1817 c.prec = 16
1818 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001819
Stefan Krah1919b7e2012-03-21 18:25:23 +01001820 self.assertEqual(h1, h2)
1821 self.assertEqual(h1, h3)
1822
1823 c.prec = 10000
1824 x = 1100 ** 1248
1825 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001826
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001827 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001828 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001829
1830 d1 = Decimal('15.32')
1831 d2 = Decimal('28.5')
1832 l1 = 15
1833 l2 = 28
1834
1835 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001836 self.assertIs(min(d1,d2), d1)
1837 self.assertIs(min(d2,d1), d1)
1838 self.assertIs(max(d1,d2), d2)
1839 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001840
1841 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001842 self.assertIs(min(d1,l2), d1)
1843 self.assertIs(min(l2,d1), d1)
1844 self.assertIs(max(l1,d2), d2)
1845 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001846
1847 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001848 Decimal = self.decimal.Decimal
1849
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001850 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001851 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001852 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001853 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001854
1855 def test_tostring_methods(self):
1856 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001857 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001858
1859 d = Decimal('15.32')
1860 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001861 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001862
1863 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001864 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001865 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001866
1867 d1 = Decimal('66')
1868 d2 = Decimal('15.32')
1869
1870 #int
1871 self.assertEqual(int(d1), 66)
1872 self.assertEqual(int(d2), 15)
1873
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001874 #float
1875 self.assertEqual(float(d1), 66)
1876 self.assertEqual(float(d2), 15.32)
1877
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001878 #floor
1879 test_pairs = [
1880 ('123.00', 123),
1881 ('3.2', 3),
1882 ('3.54', 3),
1883 ('3.899', 3),
1884 ('-2.3', -3),
1885 ('-11.0', -11),
1886 ('0.0', 0),
1887 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001888 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001889 ]
1890 for d, i in test_pairs:
1891 self.assertEqual(math.floor(Decimal(d)), i)
1892 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1893 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1894 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1895 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1896 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1897
1898 #ceiling
1899 test_pairs = [
1900 ('123.00', 123),
1901 ('3.2', 4),
1902 ('3.54', 4),
1903 ('3.899', 4),
1904 ('-2.3', -2),
1905 ('-11.0', -11),
1906 ('0.0', 0),
1907 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001908 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001909 ]
1910 for d, i in test_pairs:
1911 self.assertEqual(math.ceil(Decimal(d)), i)
1912 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1913 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1914 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1915 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1916 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1917
1918 #round, single argument
1919 test_pairs = [
1920 ('123.00', 123),
1921 ('3.2', 3),
1922 ('3.54', 4),
1923 ('3.899', 4),
1924 ('-2.3', -2),
1925 ('-11.0', -11),
1926 ('0.0', 0),
1927 ('-0E3', 0),
1928 ('-3.5', -4),
1929 ('-2.5', -2),
1930 ('-1.5', -2),
1931 ('-0.5', 0),
1932 ('0.5', 0),
1933 ('1.5', 2),
1934 ('2.5', 2),
1935 ('3.5', 4),
1936 ]
1937 for d, i in test_pairs:
1938 self.assertEqual(round(Decimal(d)), i)
1939 self.assertRaises(ValueError, round, Decimal('-NaN'))
1940 self.assertRaises(ValueError, round, Decimal('sNaN'))
1941 self.assertRaises(ValueError, round, Decimal('NaN123'))
1942 self.assertRaises(OverflowError, round, Decimal('Inf'))
1943 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1944
1945 #round, two arguments; this is essentially equivalent
1946 #to quantize, which is already extensively tested
1947 test_triples = [
1948 ('123.456', -4, '0E+4'),
1949 ('123.456', -3, '0E+3'),
1950 ('123.456', -2, '1E+2'),
1951 ('123.456', -1, '1.2E+2'),
1952 ('123.456', 0, '123'),
1953 ('123.456', 1, '123.5'),
1954 ('123.456', 2, '123.46'),
1955 ('123.456', 3, '123.456'),
1956 ('123.456', 4, '123.4560'),
1957 ('123.455', 2, '123.46'),
1958 ('123.445', 2, '123.44'),
1959 ('Inf', 4, 'NaN'),
1960 ('-Inf', -23, 'NaN'),
1961 ('sNaN314', 3, 'NaN314'),
1962 ]
1963 for d, n, r in test_triples:
1964 self.assertEqual(str(round(Decimal(d), n)), r)
1965
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001966 def test_nan_to_float(self):
1967 # Test conversions of decimal NANs to float.
1968 # See http://bugs.python.org/issue15544
1969 Decimal = self.decimal.Decimal
1970 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1971 f = float(Decimal(s))
1972 self.assertTrue(math.isnan(f))
1973 sign = math.copysign(1.0, f)
1974 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1975
1976 def test_snan_to_float(self):
1977 Decimal = self.decimal.Decimal
1978 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1979 d = Decimal(s)
1980 self.assertRaises(ValueError, float, d)
1981
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001982 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001983 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001984
1985 #with zero
1986 d = Decimal( (0, (0,), 0) )
1987 self.assertEqual(d, eval(repr(d)))
1988
1989 #int
1990 d = Decimal( (1, (4, 5), 0) )
1991 self.assertEqual(d, eval(repr(d)))
1992
1993 #float
1994 d = Decimal( (0, (4, 5, 3, 4), -2) )
1995 self.assertEqual(d, eval(repr(d)))
1996
1997 #weird
1998 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1999 self.assertEqual(d, eval(repr(d)))
2000
2001 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002002 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002003
2004 #with zero
2005 d = Decimal(0)
2006 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
2007
2008 #int
2009 d = Decimal(-45)
2010 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2011
2012 #complicated string
2013 d = Decimal("-4.34913534E-17")
2014 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2015
Stefan Krah76e12172012-09-10 19:34:58 +02002016 # The '0' coefficient is implementation specific to decimal.py.
2017 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002018 d = Decimal("Infinity")
2019 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2020
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002021 #leading zeros in coefficient should be stripped
2022 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2023 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2024 d = Decimal( (1, (0, 0, 0), 37) )
2025 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2026 d = Decimal( (1, (), 37) )
2027 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2028
2029 #leading zeros in NaN diagnostic info should be stripped
2030 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2031 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2032 d = Decimal( (1, (0, 0, 0), 'N') )
2033 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2034 d = Decimal( (1, (), 'n') )
2035 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2036
Stefan Krah76e12172012-09-10 19:34:58 +02002037 # For infinities, decimal.py has always silently accepted any
2038 # coefficient tuple.
2039 d = Decimal( (0, (0,), 'F') )
2040 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2041 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2042 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2043 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2044 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002045
Stefan Krah1919b7e2012-03-21 18:25:23 +01002046 def test_subclassing(self):
2047 # Different behaviours when subclassing Decimal
2048 Decimal = self.decimal.Decimal
2049
2050 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002051 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002052
2053 d1 = MyDecimal(1)
2054 d2 = MyDecimal(2)
2055 d = d1 + d2
2056 self.assertIs(type(d), Decimal)
2057
2058 d = d1.max(d2)
2059 self.assertIs(type(d), Decimal)
2060
2061 d = copy.copy(d1)
2062 self.assertIs(type(d), MyDecimal)
2063 self.assertEqual(d, d1)
2064
2065 d = copy.deepcopy(d1)
2066 self.assertIs(type(d), MyDecimal)
2067 self.assertEqual(d, d1)
2068
Stefan Krah0f82b762012-11-08 11:17:29 +01002069 # Decimal(Decimal)
2070 d = Decimal('1.0')
2071 x = Decimal(d)
2072 self.assertIs(type(x), Decimal)
2073 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002074
Stefan Krah0f82b762012-11-08 11:17:29 +01002075 # MyDecimal(Decimal)
2076 m = MyDecimal(d)
2077 self.assertIs(type(m), MyDecimal)
2078 self.assertEqual(m, d)
2079 self.assertIs(m.y, None)
2080
2081 # Decimal(MyDecimal)
2082 x = Decimal(m)
2083 self.assertIs(type(x), Decimal)
2084 self.assertEqual(x, d)
2085
2086 # MyDecimal(MyDecimal)
2087 m.y = 9
2088 x = MyDecimal(m)
2089 self.assertIs(type(x), MyDecimal)
2090 self.assertEqual(x, d)
2091 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002092
Stefan Krah1919b7e2012-03-21 18:25:23 +01002093 def test_implicit_context(self):
2094 Decimal = self.decimal.Decimal
2095 getcontext = self.decimal.getcontext
2096
2097 # Check results when context given implicitly. (Issue 2478)
2098 c = getcontext()
2099 self.assertEqual(str(Decimal(0).sqrt()),
2100 str(c.sqrt(Decimal(0))))
2101
Stefan Krah040e3112012-12-15 22:33:33 +01002102 def test_none_args(self):
2103 Decimal = self.decimal.Decimal
2104 Context = self.decimal.Context
2105 localcontext = self.decimal.localcontext
2106 InvalidOperation = self.decimal.InvalidOperation
2107 DivisionByZero = self.decimal.DivisionByZero
2108 Overflow = self.decimal.Overflow
2109 Underflow = self.decimal.Underflow
2110 Subnormal = self.decimal.Subnormal
2111 Inexact = self.decimal.Inexact
2112 Rounded = self.decimal.Rounded
2113 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002114
2115 with localcontext(Context()) as c:
2116 c.prec = 7
2117 c.Emax = 999
2118 c.Emin = -999
2119
2120 x = Decimal("111")
2121 y = Decimal("1e9999")
2122 z = Decimal("1e-9999")
2123
2124 ##### Unary functions
2125 c.clear_flags()
2126 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2127 self.assertTrue(c.flags[Inexact])
2128 self.assertTrue(c.flags[Rounded])
2129 c.clear_flags()
2130 self.assertRaises(Overflow, y.exp, context=None)
2131 self.assertTrue(c.flags[Overflow])
2132
2133 self.assertIs(z.is_normal(context=None), False)
2134 self.assertIs(z.is_subnormal(context=None), True)
2135
2136 c.clear_flags()
2137 self.assertEqual(str(x.ln(context=None)), '4.709530')
2138 self.assertTrue(c.flags[Inexact])
2139 self.assertTrue(c.flags[Rounded])
2140 c.clear_flags()
2141 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2142 self.assertTrue(c.flags[InvalidOperation])
2143
2144 c.clear_flags()
2145 self.assertEqual(str(x.log10(context=None)), '2.045323')
2146 self.assertTrue(c.flags[Inexact])
2147 self.assertTrue(c.flags[Rounded])
2148 c.clear_flags()
2149 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2150 self.assertTrue(c.flags[InvalidOperation])
2151
2152 c.clear_flags()
2153 self.assertEqual(str(x.logb(context=None)), '2')
2154 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2155 self.assertTrue(c.flags[DivisionByZero])
2156
2157 c.clear_flags()
2158 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2159 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2160 self.assertTrue(c.flags[InvalidOperation])
2161
2162 c.clear_flags()
2163 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2164 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2165 self.assertTrue(c.flags[InvalidOperation])
2166
2167 c.clear_flags()
2168 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2169 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2170 self.assertTrue(c.flags[InvalidOperation])
2171
2172 c.clear_flags()
2173 self.assertEqual(str(z.normalize(context=None)), '0')
2174 self.assertRaises(Overflow, y.normalize, context=None)
2175 self.assertTrue(c.flags[Overflow])
2176
2177 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2178
2179 c.clear_flags()
2180 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2181 self.assertTrue(c.flags[Clamped])
2182 self.assertTrue(c.flags[Inexact])
2183 self.assertTrue(c.flags[Rounded])
2184 self.assertTrue(c.flags[Subnormal])
2185 self.assertTrue(c.flags[Underflow])
2186 c.clear_flags()
2187 self.assertRaises(Overflow, y.sqrt, context=None)
2188 self.assertTrue(c.flags[Overflow])
2189
2190 c.capitals = 0
2191 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2192 c.capitals = 1
2193
2194
2195 ##### Binary functions
2196 c.clear_flags()
2197 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2198 self.assertEqual(ans, 'NaN1287828')
2199 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2200 self.assertTrue(c.flags[InvalidOperation])
2201
2202 c.clear_flags()
2203 ans = str(x.compare_signal(8224, context=None))
2204 self.assertEqual(ans, '-1')
2205 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2206 self.assertTrue(c.flags[InvalidOperation])
2207
2208 c.clear_flags()
2209 ans = str(x.logical_and(101, context=None))
2210 self.assertEqual(ans, '101')
2211 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2212 self.assertTrue(c.flags[InvalidOperation])
2213
2214 c.clear_flags()
2215 ans = str(x.logical_or(101, context=None))
2216 self.assertEqual(ans, '111')
2217 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2218 self.assertTrue(c.flags[InvalidOperation])
2219
2220 c.clear_flags()
2221 ans = str(x.logical_xor(101, context=None))
2222 self.assertEqual(ans, '10')
2223 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2224 self.assertTrue(c.flags[InvalidOperation])
2225
2226 c.clear_flags()
2227 ans = str(x.max(101, context=None))
2228 self.assertEqual(ans, '111')
2229 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2230 self.assertTrue(c.flags[InvalidOperation])
2231
2232 c.clear_flags()
2233 ans = str(x.max_mag(101, context=None))
2234 self.assertEqual(ans, '111')
2235 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2236 self.assertTrue(c.flags[InvalidOperation])
2237
2238 c.clear_flags()
2239 ans = str(x.min(101, context=None))
2240 self.assertEqual(ans, '101')
2241 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2242 self.assertTrue(c.flags[InvalidOperation])
2243
2244 c.clear_flags()
2245 ans = str(x.min_mag(101, context=None))
2246 self.assertEqual(ans, '101')
2247 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2248 self.assertTrue(c.flags[InvalidOperation])
2249
2250 c.clear_flags()
2251 ans = str(x.remainder_near(101, context=None))
2252 self.assertEqual(ans, '10')
2253 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2254 self.assertTrue(c.flags[InvalidOperation])
2255
2256 c.clear_flags()
2257 ans = str(x.rotate(2, context=None))
2258 self.assertEqual(ans, '11100')
2259 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2260 self.assertTrue(c.flags[InvalidOperation])
2261
2262 c.clear_flags()
2263 ans = str(x.scaleb(7, context=None))
2264 self.assertEqual(ans, '1.11E+9')
2265 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2266 self.assertTrue(c.flags[InvalidOperation])
2267
2268 c.clear_flags()
2269 ans = str(x.shift(2, context=None))
2270 self.assertEqual(ans, '11100')
2271 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2272 self.assertTrue(c.flags[InvalidOperation])
2273
2274
2275 ##### Ternary functions
2276 c.clear_flags()
2277 ans = str(x.fma(2, 3, context=None))
2278 self.assertEqual(ans, '225')
2279 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2280 self.assertTrue(c.flags[Overflow])
2281
2282
2283 ##### Special cases
2284 c.rounding = ROUND_HALF_EVEN
2285 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2286 self.assertEqual(ans, '2')
2287 c.rounding = ROUND_DOWN
2288 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2289 self.assertEqual(ans, '1')
2290 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2291 self.assertEqual(ans, '2')
2292 c.clear_flags()
2293 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2294 self.assertTrue(c.flags[InvalidOperation])
2295
2296 c.rounding = ROUND_HALF_EVEN
2297 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2298 self.assertEqual(ans, '2')
2299 c.rounding = ROUND_DOWN
2300 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2301 self.assertEqual(ans, '1')
2302 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2303 self.assertEqual(ans, '2')
2304 c.clear_flags()
2305 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2306 self.assertTrue(c.flags[InvalidOperation])
2307
2308 c.rounding = ROUND_HALF_EVEN
2309 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2310 self.assertEqual(ans, '2')
2311 c.rounding = ROUND_DOWN
2312 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2313 self.assertEqual(ans, '1')
2314 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2315 self.assertEqual(ans, '2')
2316 c.clear_flags()
2317 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2318 self.assertTrue(c.flags[InvalidOperation])
2319
2320 c.rounding = ROUND_UP
2321 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2322 self.assertEqual(ans, '1.501')
2323 c.rounding = ROUND_DOWN
2324 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2325 self.assertEqual(ans, '1.500')
2326 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2327 self.assertEqual(ans, '1.501')
2328 c.clear_flags()
2329 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2330 self.assertTrue(c.flags[InvalidOperation])
2331
2332 with localcontext(Context()) as context:
2333 context.prec = 7
2334 context.Emax = 999
2335 context.Emin = -999
2336 with localcontext(ctx=None) as c:
2337 self.assertEqual(c.prec, 7)
2338 self.assertEqual(c.Emax, 999)
2339 self.assertEqual(c.Emin, -999)
2340
Stefan Krah1919b7e2012-03-21 18:25:23 +01002341 def test_conversions_from_int(self):
2342 # Check that methods taking a second Decimal argument will
2343 # always accept an integer in place of a Decimal.
2344 Decimal = self.decimal.Decimal
2345
2346 self.assertEqual(Decimal(4).compare(3),
2347 Decimal(4).compare(Decimal(3)))
2348 self.assertEqual(Decimal(4).compare_signal(3),
2349 Decimal(4).compare_signal(Decimal(3)))
2350 self.assertEqual(Decimal(4).compare_total(3),
2351 Decimal(4).compare_total(Decimal(3)))
2352 self.assertEqual(Decimal(4).compare_total_mag(3),
2353 Decimal(4).compare_total_mag(Decimal(3)))
2354 self.assertEqual(Decimal(10101).logical_and(1001),
2355 Decimal(10101).logical_and(Decimal(1001)))
2356 self.assertEqual(Decimal(10101).logical_or(1001),
2357 Decimal(10101).logical_or(Decimal(1001)))
2358 self.assertEqual(Decimal(10101).logical_xor(1001),
2359 Decimal(10101).logical_xor(Decimal(1001)))
2360 self.assertEqual(Decimal(567).max(123),
2361 Decimal(567).max(Decimal(123)))
2362 self.assertEqual(Decimal(567).max_mag(123),
2363 Decimal(567).max_mag(Decimal(123)))
2364 self.assertEqual(Decimal(567).min(123),
2365 Decimal(567).min(Decimal(123)))
2366 self.assertEqual(Decimal(567).min_mag(123),
2367 Decimal(567).min_mag(Decimal(123)))
2368 self.assertEqual(Decimal(567).next_toward(123),
2369 Decimal(567).next_toward(Decimal(123)))
2370 self.assertEqual(Decimal(1234).quantize(100),
2371 Decimal(1234).quantize(Decimal(100)))
2372 self.assertEqual(Decimal(768).remainder_near(1234),
2373 Decimal(768).remainder_near(Decimal(1234)))
2374 self.assertEqual(Decimal(123).rotate(1),
2375 Decimal(123).rotate(Decimal(1)))
2376 self.assertEqual(Decimal(1234).same_quantum(1000),
2377 Decimal(1234).same_quantum(Decimal(1000)))
2378 self.assertEqual(Decimal('9.123').scaleb(-100),
2379 Decimal('9.123').scaleb(Decimal(-100)))
2380 self.assertEqual(Decimal(456).shift(-1),
2381 Decimal(456).shift(Decimal(-1)))
2382
2383 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2384 Decimal(-12).fma(Decimal(45), Decimal(67)))
2385 self.assertEqual(Decimal(-12).fma(45, 67),
2386 Decimal(-12).fma(Decimal(45), Decimal(67)))
2387 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2388 Decimal(-12).fma(Decimal(45), Decimal(67)))
2389
2390class CUsabilityTest(UsabilityTest):
2391 decimal = C
2392class PyUsabilityTest(UsabilityTest):
2393 decimal = P
2394
2395class PythonAPItests(unittest.TestCase):
2396
2397 def test_abc(self):
2398 Decimal = self.decimal.Decimal
2399
2400 self.assertTrue(issubclass(Decimal, numbers.Number))
2401 self.assertFalse(issubclass(Decimal, numbers.Real))
2402 self.assertIsInstance(Decimal(0), numbers.Number)
2403 self.assertNotIsInstance(Decimal(0), numbers.Real)
2404
2405 def test_pickle(self):
2406 Decimal = self.decimal.Decimal
2407
2408 savedecimal = sys.modules['decimal']
2409
2410 # Round trip
2411 sys.modules['decimal'] = self.decimal
2412 d = Decimal('-3.141590000')
2413 p = pickle.dumps(d)
2414 e = pickle.loads(p)
2415 self.assertEqual(d, e)
2416
2417 if C:
2418 # Test interchangeability
2419 x = C.Decimal('-3.123e81723')
2420 y = P.Decimal('-3.123e81723')
2421
2422 sys.modules['decimal'] = C
2423 sx = pickle.dumps(x)
2424 sys.modules['decimal'] = P
2425 r = pickle.loads(sx)
2426 self.assertIsInstance(r, P.Decimal)
2427 self.assertEqual(r, y)
2428
2429 sys.modules['decimal'] = P
2430 sy = pickle.dumps(y)
2431 sys.modules['decimal'] = C
2432 r = pickle.loads(sy)
2433 self.assertIsInstance(r, C.Decimal)
2434 self.assertEqual(r, x)
2435
2436 sys.modules['decimal'] = savedecimal
2437
2438 def test_int(self):
2439 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002440
2441 for x in range(-250, 250):
2442 s = '%0.2f' % (x / 100.0)
2443 # should work the same as for floats
2444 self.assertEqual(int(Decimal(s)), int(float(s)))
2445 # should work the same as to_integral in the ROUND_DOWN mode
2446 d = Decimal(s)
2447 r = d.to_integral(ROUND_DOWN)
2448 self.assertEqual(Decimal(int(d)), r)
2449
2450 self.assertRaises(ValueError, int, Decimal('-nan'))
2451 self.assertRaises(ValueError, int, Decimal('snan'))
2452 self.assertRaises(OverflowError, int, Decimal('inf'))
2453 self.assertRaises(OverflowError, int, Decimal('-inf'))
2454
2455 def test_trunc(self):
2456 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002457
2458 for x in range(-250, 250):
2459 s = '%0.2f' % (x / 100.0)
2460 # should work the same as for floats
2461 self.assertEqual(int(Decimal(s)), int(float(s)))
2462 # should work the same as to_integral in the ROUND_DOWN mode
2463 d = Decimal(s)
2464 r = d.to_integral(ROUND_DOWN)
2465 self.assertEqual(Decimal(math.trunc(d)), r)
2466
2467 def test_from_float(self):
2468
2469 Decimal = self.decimal.Decimal
2470
2471 class MyDecimal(Decimal):
2472 pass
2473
2474 self.assertTrue(issubclass(MyDecimal, Decimal))
2475
2476 r = MyDecimal.from_float(0.1)
2477 self.assertEqual(type(r), MyDecimal)
2478 self.assertEqual(str(r),
2479 '0.1000000000000000055511151231257827021181583404541015625')
2480 bigint = 12345678901234567890123456789
2481 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2482 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2483 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2484 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2485 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2486 str(Decimal('NaN')))
2487 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2488 str(Decimal('Infinity')))
2489 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2490 str(Decimal('-Infinity')))
2491 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2492 for i in range(200):
2493 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2494 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2495
2496 def test_create_decimal_from_float(self):
2497 Decimal = self.decimal.Decimal
2498 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002499 Inexact = self.decimal.Inexact
2500
2501 context = Context(prec=5, rounding=ROUND_DOWN)
2502 self.assertEqual(
2503 context.create_decimal_from_float(math.pi),
2504 Decimal('3.1415')
2505 )
2506 context = Context(prec=5, rounding=ROUND_UP)
2507 self.assertEqual(
2508 context.create_decimal_from_float(math.pi),
2509 Decimal('3.1416')
2510 )
2511 context = Context(prec=5, traps=[Inexact])
2512 self.assertRaises(
2513 Inexact,
2514 context.create_decimal_from_float,
2515 math.pi
2516 )
2517 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2518 "Decimal('-0')")
2519 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2520 "Decimal('1')")
2521 self.assertEqual(repr(context.create_decimal_from_float(10)),
2522 "Decimal('10')")
2523
2524 def test_quantize(self):
2525 Decimal = self.decimal.Decimal
2526 Context = self.decimal.Context
2527 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002528
2529 c = Context(Emax=99999, Emin=-99999)
2530 self.assertEqual(
2531 Decimal('7.335').quantize(Decimal('.01')),
2532 Decimal('7.34')
2533 )
2534 self.assertEqual(
2535 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2536 Decimal('7.33')
2537 )
2538 self.assertRaises(
2539 InvalidOperation,
2540 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2541 )
2542
2543 c = Context()
2544 d = Decimal("0.871831e800")
2545 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2546 self.assertEqual(x, Decimal('8.71E+799'))
2547
2548 def test_complex(self):
2549 Decimal = self.decimal.Decimal
2550
2551 x = Decimal("9.8182731e181273")
2552 self.assertEqual(x.real, x)
2553 self.assertEqual(x.imag, 0)
2554 self.assertEqual(x.conjugate(), x)
2555
2556 x = Decimal("1")
2557 self.assertEqual(complex(x), complex(float(1)))
2558
2559 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2560 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2561 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2562 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2563
2564 def test_named_parameters(self):
2565 D = self.decimal.Decimal
2566 Context = self.decimal.Context
2567 localcontext = self.decimal.localcontext
2568 InvalidOperation = self.decimal.InvalidOperation
2569 Overflow = self.decimal.Overflow
2570
2571 xc = Context()
2572 xc.prec = 1
2573 xc.Emax = 1
2574 xc.Emin = -1
2575
2576 with localcontext() as c:
2577 c.clear_flags()
2578
2579 self.assertEqual(D(9, xc), 9)
2580 self.assertEqual(D(9, context=xc), 9)
2581 self.assertEqual(D(context=xc, value=9), 9)
2582 self.assertEqual(D(context=xc), 0)
2583 xc.clear_flags()
2584 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2585 self.assertTrue(xc.flags[InvalidOperation])
2586 self.assertFalse(c.flags[InvalidOperation])
2587
2588 xc.clear_flags()
2589 self.assertEqual(D(2).exp(context=xc), 7)
2590 self.assertRaises(Overflow, D(8).exp, context=xc)
2591 self.assertTrue(xc.flags[Overflow])
2592 self.assertFalse(c.flags[Overflow])
2593
2594 xc.clear_flags()
2595 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2596 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2597 self.assertTrue(xc.flags[InvalidOperation])
2598 self.assertFalse(c.flags[InvalidOperation])
2599
2600 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2601 self.assertEqual(D(-1).next_minus(context=xc), -2)
2602 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2603 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2604 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2605 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2606 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2607 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2608
2609 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2610 xc.clear_flags()
2611 self.assertRaises(InvalidOperation,
2612 D("0").compare_signal, D('nan'), context=xc)
2613 self.assertTrue(xc.flags[InvalidOperation])
2614 self.assertFalse(c.flags[InvalidOperation])
2615 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2616 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2617 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2618 D('-0.3'))
2619 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2620 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2621 D('0.0'))
2622 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2623 xc.clear_flags()
2624 self.assertRaises(InvalidOperation,
2625 D("0.2").quantize, D('1e10'), context=xc)
2626 self.assertTrue(xc.flags[InvalidOperation])
2627 self.assertFalse(c.flags[InvalidOperation])
2628 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2629 D('-0.5'))
2630
2631 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2632 D('7E+1'))
2633
2634 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2635 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2636 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2637 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2638 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2639 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2640 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2641 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2642
2643 self.assertFalse(D("0.01").is_normal(context=xc))
2644 self.assertTrue(D("0.01").is_subnormal(context=xc))
2645
2646 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2647 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2648 self.assertRaises(TypeError, D(1).radix, context=xc)
2649
2650 self.assertEqual(D(-111).logb(context=xc), 2)
2651 self.assertEqual(D(0).logical_invert(context=xc), 1)
2652 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2653 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2654
2655 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2656 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2657 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2658 self.assertEqual(D('23').rotate(1, context=xc), 3)
2659 self.assertEqual(D('23').rotate(1, context=xc), 3)
2660 xc.clear_flags()
2661 self.assertRaises(Overflow,
2662 D('23').scaleb, 1, context=xc)
2663 self.assertTrue(xc.flags[Overflow])
2664 self.assertFalse(c.flags[Overflow])
2665 self.assertEqual(D('23').shift(-1, context=xc), 0)
2666
2667 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2668 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2669
Stefan Krah040e3112012-12-15 22:33:33 +01002670 self.assertEqual(D(1).canonical(), 1)
2671 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2672 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2673 self.assertRaises(TypeError, D(1).canonical, context="x")
2674 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002675
Stefan Krahb6405ef2012-03-23 14:46:48 +01002676 def test_exception_hierarchy(self):
2677
2678 decimal = self.decimal
2679 DecimalException = decimal.DecimalException
2680 InvalidOperation = decimal.InvalidOperation
2681 FloatOperation = decimal.FloatOperation
2682 DivisionByZero = decimal.DivisionByZero
2683 Overflow = decimal.Overflow
2684 Underflow = decimal.Underflow
2685 Subnormal = decimal.Subnormal
2686 Inexact = decimal.Inexact
2687 Rounded = decimal.Rounded
2688 Clamped = decimal.Clamped
2689
2690 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2691
2692 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2693 self.assertTrue(issubclass(FloatOperation, DecimalException))
2694 self.assertTrue(issubclass(FloatOperation, TypeError))
2695 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2696 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2697 self.assertTrue(issubclass(Overflow, Rounded))
2698 self.assertTrue(issubclass(Overflow, Inexact))
2699 self.assertTrue(issubclass(Overflow, DecimalException))
2700 self.assertTrue(issubclass(Underflow, Inexact))
2701 self.assertTrue(issubclass(Underflow, Rounded))
2702 self.assertTrue(issubclass(Underflow, Subnormal))
2703 self.assertTrue(issubclass(Underflow, DecimalException))
2704
2705 self.assertTrue(issubclass(Subnormal, DecimalException))
2706 self.assertTrue(issubclass(Inexact, DecimalException))
2707 self.assertTrue(issubclass(Rounded, DecimalException))
2708 self.assertTrue(issubclass(Clamped, DecimalException))
2709
2710 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2711 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2712 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2713 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2714 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2715
Stefan Krah1919b7e2012-03-21 18:25:23 +01002716class CPythonAPItests(PythonAPItests):
2717 decimal = C
2718class PyPythonAPItests(PythonAPItests):
2719 decimal = P
2720
2721class ContextAPItests(unittest.TestCase):
2722
Stefan Krah9a4ff432012-12-16 21:10:35 +01002723 def test_none_args(self):
2724 Context = self.decimal.Context
2725 InvalidOperation = self.decimal.InvalidOperation
2726 DivisionByZero = self.decimal.DivisionByZero
2727 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002728
2729 c1 = Context()
2730 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2731 capitals=None, clamp=None, flags=None, traps=None)
2732 for c in [c1, c2]:
2733 self.assertEqual(c.prec, 28)
2734 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2735 self.assertEqual(c.Emax, 999999)
2736 self.assertEqual(c.Emin, -999999)
2737 self.assertEqual(c.capitals, 1)
2738 self.assertEqual(c.clamp, 0)
2739 assert_signals(self, c, 'flags', [])
2740 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2741 Overflow])
2742
Stefan Krah59a4a932013-01-16 12:58:59 +01002743 @cpython_only
2744 def test_from_legacy_strings(self):
2745 import _testcapi
2746 c = self.decimal.Context()
2747
2748 for rnd in RoundingModes:
2749 c.rounding = _testcapi.unicode_legacy_string(rnd)
2750 self.assertEqual(c.rounding, rnd)
2751
2752 s = _testcapi.unicode_legacy_string('')
2753 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2754
2755 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2756 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2757
Stefan Krah1919b7e2012-03-21 18:25:23 +01002758 def test_pickle(self):
2759
2760 Context = self.decimal.Context
2761
2762 savedecimal = sys.modules['decimal']
2763
2764 # Round trip
2765 sys.modules['decimal'] = self.decimal
2766 c = Context()
2767 e = pickle.loads(pickle.dumps(c))
2768
2769 self.assertEqual(c.prec, e.prec)
2770 self.assertEqual(c.Emin, e.Emin)
2771 self.assertEqual(c.Emax, e.Emax)
2772 self.assertEqual(c.rounding, e.rounding)
2773 self.assertEqual(c.capitals, e.capitals)
2774 self.assertEqual(c.clamp, e.clamp)
2775 self.assertEqual(c.flags, e.flags)
2776 self.assertEqual(c.traps, e.traps)
2777
2778 # Test interchangeability
2779 combinations = [(C, P), (P, C)] if C else [(P, P)]
2780 for dumper, loader in combinations:
Stefan Krah59a4a932013-01-16 12:58:59 +01002781 for ri, _ in enumerate(RoundingModes):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002782 for fi, _ in enumerate(OrderedSignals[dumper]):
2783 for ti, _ in enumerate(OrderedSignals[dumper]):
2784
2785 prec = random.randrange(1, 100)
2786 emin = random.randrange(-100, 0)
2787 emax = random.randrange(1, 100)
2788 caps = random.randrange(2)
2789 clamp = random.randrange(2)
2790
2791 # One module dumps
2792 sys.modules['decimal'] = dumper
2793 c = dumper.Context(
2794 prec=prec, Emin=emin, Emax=emax,
Stefan Krah59a4a932013-01-16 12:58:59 +01002795 rounding=RoundingModes[ri],
Stefan Krah1919b7e2012-03-21 18:25:23 +01002796 capitals=caps, clamp=clamp,
2797 flags=OrderedSignals[dumper][:fi],
2798 traps=OrderedSignals[dumper][:ti]
2799 )
2800 s = pickle.dumps(c)
2801
2802 # The other module loads
2803 sys.modules['decimal'] = loader
2804 d = pickle.loads(s)
2805 self.assertIsInstance(d, loader.Context)
2806
2807 self.assertEqual(d.prec, prec)
2808 self.assertEqual(d.Emin, emin)
2809 self.assertEqual(d.Emax, emax)
Stefan Krah59a4a932013-01-16 12:58:59 +01002810 self.assertEqual(d.rounding, RoundingModes[ri])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002811 self.assertEqual(d.capitals, caps)
2812 self.assertEqual(d.clamp, clamp)
2813 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2814 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2815
2816 sys.modules['decimal'] = savedecimal
2817
2818 def test_equality_with_other_types(self):
2819 Decimal = self.decimal.Decimal
2820
2821 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2822 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2823
2824 def test_copy(self):
2825 # All copies should be deep
2826 Decimal = self.decimal.Decimal
2827 Context = self.decimal.Context
2828
2829 c = Context()
2830 d = c.copy()
2831 self.assertNotEqual(id(c), id(d))
2832 self.assertNotEqual(id(c.flags), id(d.flags))
2833 self.assertNotEqual(id(c.traps), id(d.traps))
2834 k1 = set(c.flags.keys())
2835 k2 = set(d.flags.keys())
2836 self.assertEqual(k1, k2)
2837 self.assertEqual(c.flags, d.flags)
2838
2839 def test__clamp(self):
2840 # In Python 3.2, the private attribute `_clamp` was made
2841 # public (issue 8540), with the old `_clamp` becoming a
2842 # property wrapping `clamp`. For the duration of Python 3.2
2843 # only, the attribute should be gettable/settable via both
2844 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2845 # removed.
2846 Context = self.decimal.Context
2847 c = Context()
2848 self.assertRaises(AttributeError, getattr, c, '_clamp')
2849
2850 def test_abs(self):
2851 Decimal = self.decimal.Decimal
2852 Context = self.decimal.Context
2853
2854 c = Context()
2855 d = c.abs(Decimal(-1))
2856 self.assertEqual(c.abs(-1), d)
2857 self.assertRaises(TypeError, c.abs, '-1')
2858
2859 def test_add(self):
2860 Decimal = self.decimal.Decimal
2861 Context = self.decimal.Context
2862
2863 c = Context()
2864 d = c.add(Decimal(1), Decimal(1))
2865 self.assertEqual(c.add(1, 1), d)
2866 self.assertEqual(c.add(Decimal(1), 1), d)
2867 self.assertEqual(c.add(1, Decimal(1)), d)
2868 self.assertRaises(TypeError, c.add, '1', 1)
2869 self.assertRaises(TypeError, c.add, 1, '1')
2870
2871 def test_compare(self):
2872 Decimal = self.decimal.Decimal
2873 Context = self.decimal.Context
2874
2875 c = Context()
2876 d = c.compare(Decimal(1), Decimal(1))
2877 self.assertEqual(c.compare(1, 1), d)
2878 self.assertEqual(c.compare(Decimal(1), 1), d)
2879 self.assertEqual(c.compare(1, Decimal(1)), d)
2880 self.assertRaises(TypeError, c.compare, '1', 1)
2881 self.assertRaises(TypeError, c.compare, 1, '1')
2882
2883 def test_compare_signal(self):
2884 Decimal = self.decimal.Decimal
2885 Context = self.decimal.Context
2886
2887 c = Context()
2888 d = c.compare_signal(Decimal(1), Decimal(1))
2889 self.assertEqual(c.compare_signal(1, 1), d)
2890 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2891 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2892 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2893 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2894
2895 def test_compare_total(self):
2896 Decimal = self.decimal.Decimal
2897 Context = self.decimal.Context
2898
2899 c = Context()
2900 d = c.compare_total(Decimal(1), Decimal(1))
2901 self.assertEqual(c.compare_total(1, 1), d)
2902 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2903 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2904 self.assertRaises(TypeError, c.compare_total, '1', 1)
2905 self.assertRaises(TypeError, c.compare_total, 1, '1')
2906
2907 def test_compare_total_mag(self):
2908 Decimal = self.decimal.Decimal
2909 Context = self.decimal.Context
2910
2911 c = Context()
2912 d = c.compare_total_mag(Decimal(1), Decimal(1))
2913 self.assertEqual(c.compare_total_mag(1, 1), d)
2914 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2915 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2916 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2917 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2918
2919 def test_copy_abs(self):
2920 Decimal = self.decimal.Decimal
2921 Context = self.decimal.Context
2922
2923 c = Context()
2924 d = c.copy_abs(Decimal(-1))
2925 self.assertEqual(c.copy_abs(-1), d)
2926 self.assertRaises(TypeError, c.copy_abs, '-1')
2927
2928 def test_copy_decimal(self):
2929 Decimal = self.decimal.Decimal
2930 Context = self.decimal.Context
2931
2932 c = Context()
2933 d = c.copy_decimal(Decimal(-1))
2934 self.assertEqual(c.copy_decimal(-1), d)
2935 self.assertRaises(TypeError, c.copy_decimal, '-1')
2936
2937 def test_copy_negate(self):
2938 Decimal = self.decimal.Decimal
2939 Context = self.decimal.Context
2940
2941 c = Context()
2942 d = c.copy_negate(Decimal(-1))
2943 self.assertEqual(c.copy_negate(-1), d)
2944 self.assertRaises(TypeError, c.copy_negate, '-1')
2945
2946 def test_copy_sign(self):
2947 Decimal = self.decimal.Decimal
2948 Context = self.decimal.Context
2949
2950 c = Context()
2951 d = c.copy_sign(Decimal(1), Decimal(-2))
2952 self.assertEqual(c.copy_sign(1, -2), d)
2953 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2954 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2955 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2956 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2957
2958 def test_divide(self):
2959 Decimal = self.decimal.Decimal
2960 Context = self.decimal.Context
2961
2962 c = Context()
2963 d = c.divide(Decimal(1), Decimal(2))
2964 self.assertEqual(c.divide(1, 2), d)
2965 self.assertEqual(c.divide(Decimal(1), 2), d)
2966 self.assertEqual(c.divide(1, Decimal(2)), d)
2967 self.assertRaises(TypeError, c.divide, '1', 2)
2968 self.assertRaises(TypeError, c.divide, 1, '2')
2969
2970 def test_divide_int(self):
2971 Decimal = self.decimal.Decimal
2972 Context = self.decimal.Context
2973
2974 c = Context()
2975 d = c.divide_int(Decimal(1), Decimal(2))
2976 self.assertEqual(c.divide_int(1, 2), d)
2977 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2978 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2979 self.assertRaises(TypeError, c.divide_int, '1', 2)
2980 self.assertRaises(TypeError, c.divide_int, 1, '2')
2981
2982 def test_divmod(self):
2983 Decimal = self.decimal.Decimal
2984 Context = self.decimal.Context
2985
2986 c = Context()
2987 d = c.divmod(Decimal(1), Decimal(2))
2988 self.assertEqual(c.divmod(1, 2), d)
2989 self.assertEqual(c.divmod(Decimal(1), 2), d)
2990 self.assertEqual(c.divmod(1, Decimal(2)), d)
2991 self.assertRaises(TypeError, c.divmod, '1', 2)
2992 self.assertRaises(TypeError, c.divmod, 1, '2')
2993
2994 def test_exp(self):
2995 Decimal = self.decimal.Decimal
2996 Context = self.decimal.Context
2997
2998 c = Context()
2999 d = c.exp(Decimal(10))
3000 self.assertEqual(c.exp(10), d)
3001 self.assertRaises(TypeError, c.exp, '10')
3002
3003 def test_fma(self):
3004 Decimal = self.decimal.Decimal
3005 Context = self.decimal.Context
3006
3007 c = Context()
3008 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3009 self.assertEqual(c.fma(2, 3, 4), d)
3010 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3011 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3012 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3013 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3014 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3015 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3016 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3017
3018 # Issue 12079 for Context.fma ...
3019 self.assertRaises(TypeError, c.fma,
3020 Decimal('Infinity'), Decimal(0), "not a decimal")
3021 self.assertRaises(TypeError, c.fma,
3022 Decimal(1), Decimal('snan'), 1.222)
3023 # ... and for Decimal.fma.
3024 self.assertRaises(TypeError, Decimal('Infinity').fma,
3025 Decimal(0), "not a decimal")
3026 self.assertRaises(TypeError, Decimal(1).fma,
3027 Decimal('snan'), 1.222)
3028
3029 def test_is_finite(self):
3030 Decimal = self.decimal.Decimal
3031 Context = self.decimal.Context
3032
3033 c = Context()
3034 d = c.is_finite(Decimal(10))
3035 self.assertEqual(c.is_finite(10), d)
3036 self.assertRaises(TypeError, c.is_finite, '10')
3037
3038 def test_is_infinite(self):
3039 Decimal = self.decimal.Decimal
3040 Context = self.decimal.Context
3041
3042 c = Context()
3043 d = c.is_infinite(Decimal(10))
3044 self.assertEqual(c.is_infinite(10), d)
3045 self.assertRaises(TypeError, c.is_infinite, '10')
3046
3047 def test_is_nan(self):
3048 Decimal = self.decimal.Decimal
3049 Context = self.decimal.Context
3050
3051 c = Context()
3052 d = c.is_nan(Decimal(10))
3053 self.assertEqual(c.is_nan(10), d)
3054 self.assertRaises(TypeError, c.is_nan, '10')
3055
3056 def test_is_normal(self):
3057 Decimal = self.decimal.Decimal
3058 Context = self.decimal.Context
3059
3060 c = Context()
3061 d = c.is_normal(Decimal(10))
3062 self.assertEqual(c.is_normal(10), d)
3063 self.assertRaises(TypeError, c.is_normal, '10')
3064
3065 def test_is_qnan(self):
3066 Decimal = self.decimal.Decimal
3067 Context = self.decimal.Context
3068
3069 c = Context()
3070 d = c.is_qnan(Decimal(10))
3071 self.assertEqual(c.is_qnan(10), d)
3072 self.assertRaises(TypeError, c.is_qnan, '10')
3073
3074 def test_is_signed(self):
3075 Decimal = self.decimal.Decimal
3076 Context = self.decimal.Context
3077
3078 c = Context()
3079 d = c.is_signed(Decimal(10))
3080 self.assertEqual(c.is_signed(10), d)
3081 self.assertRaises(TypeError, c.is_signed, '10')
3082
3083 def test_is_snan(self):
3084 Decimal = self.decimal.Decimal
3085 Context = self.decimal.Context
3086
3087 c = Context()
3088 d = c.is_snan(Decimal(10))
3089 self.assertEqual(c.is_snan(10), d)
3090 self.assertRaises(TypeError, c.is_snan, '10')
3091
3092 def test_is_subnormal(self):
3093 Decimal = self.decimal.Decimal
3094 Context = self.decimal.Context
3095
3096 c = Context()
3097 d = c.is_subnormal(Decimal(10))
3098 self.assertEqual(c.is_subnormal(10), d)
3099 self.assertRaises(TypeError, c.is_subnormal, '10')
3100
3101 def test_is_zero(self):
3102 Decimal = self.decimal.Decimal
3103 Context = self.decimal.Context
3104
3105 c = Context()
3106 d = c.is_zero(Decimal(10))
3107 self.assertEqual(c.is_zero(10), d)
3108 self.assertRaises(TypeError, c.is_zero, '10')
3109
3110 def test_ln(self):
3111 Decimal = self.decimal.Decimal
3112 Context = self.decimal.Context
3113
3114 c = Context()
3115 d = c.ln(Decimal(10))
3116 self.assertEqual(c.ln(10), d)
3117 self.assertRaises(TypeError, c.ln, '10')
3118
3119 def test_log10(self):
3120 Decimal = self.decimal.Decimal
3121 Context = self.decimal.Context
3122
3123 c = Context()
3124 d = c.log10(Decimal(10))
3125 self.assertEqual(c.log10(10), d)
3126 self.assertRaises(TypeError, c.log10, '10')
3127
3128 def test_logb(self):
3129 Decimal = self.decimal.Decimal
3130 Context = self.decimal.Context
3131
3132 c = Context()
3133 d = c.logb(Decimal(10))
3134 self.assertEqual(c.logb(10), d)
3135 self.assertRaises(TypeError, c.logb, '10')
3136
3137 def test_logical_and(self):
3138 Decimal = self.decimal.Decimal
3139 Context = self.decimal.Context
3140
3141 c = Context()
3142 d = c.logical_and(Decimal(1), Decimal(1))
3143 self.assertEqual(c.logical_and(1, 1), d)
3144 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3145 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3146 self.assertRaises(TypeError, c.logical_and, '1', 1)
3147 self.assertRaises(TypeError, c.logical_and, 1, '1')
3148
3149 def test_logical_invert(self):
3150 Decimal = self.decimal.Decimal
3151 Context = self.decimal.Context
3152
3153 c = Context()
3154 d = c.logical_invert(Decimal(1000))
3155 self.assertEqual(c.logical_invert(1000), d)
3156 self.assertRaises(TypeError, c.logical_invert, '1000')
3157
3158 def test_logical_or(self):
3159 Decimal = self.decimal.Decimal
3160 Context = self.decimal.Context
3161
3162 c = Context()
3163 d = c.logical_or(Decimal(1), Decimal(1))
3164 self.assertEqual(c.logical_or(1, 1), d)
3165 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3166 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3167 self.assertRaises(TypeError, c.logical_or, '1', 1)
3168 self.assertRaises(TypeError, c.logical_or, 1, '1')
3169
3170 def test_logical_xor(self):
3171 Decimal = self.decimal.Decimal
3172 Context = self.decimal.Context
3173
3174 c = Context()
3175 d = c.logical_xor(Decimal(1), Decimal(1))
3176 self.assertEqual(c.logical_xor(1, 1), d)
3177 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3178 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3179 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3180 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3181
3182 def test_max(self):
3183 Decimal = self.decimal.Decimal
3184 Context = self.decimal.Context
3185
3186 c = Context()
3187 d = c.max(Decimal(1), Decimal(2))
3188 self.assertEqual(c.max(1, 2), d)
3189 self.assertEqual(c.max(Decimal(1), 2), d)
3190 self.assertEqual(c.max(1, Decimal(2)), d)
3191 self.assertRaises(TypeError, c.max, '1', 2)
3192 self.assertRaises(TypeError, c.max, 1, '2')
3193
3194 def test_max_mag(self):
3195 Decimal = self.decimal.Decimal
3196 Context = self.decimal.Context
3197
3198 c = Context()
3199 d = c.max_mag(Decimal(1), Decimal(2))
3200 self.assertEqual(c.max_mag(1, 2), d)
3201 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3202 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3203 self.assertRaises(TypeError, c.max_mag, '1', 2)
3204 self.assertRaises(TypeError, c.max_mag, 1, '2')
3205
3206 def test_min(self):
3207 Decimal = self.decimal.Decimal
3208 Context = self.decimal.Context
3209
3210 c = Context()
3211 d = c.min(Decimal(1), Decimal(2))
3212 self.assertEqual(c.min(1, 2), d)
3213 self.assertEqual(c.min(Decimal(1), 2), d)
3214 self.assertEqual(c.min(1, Decimal(2)), d)
3215 self.assertRaises(TypeError, c.min, '1', 2)
3216 self.assertRaises(TypeError, c.min, 1, '2')
3217
3218 def test_min_mag(self):
3219 Decimal = self.decimal.Decimal
3220 Context = self.decimal.Context
3221
3222 c = Context()
3223 d = c.min_mag(Decimal(1), Decimal(2))
3224 self.assertEqual(c.min_mag(1, 2), d)
3225 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3226 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3227 self.assertRaises(TypeError, c.min_mag, '1', 2)
3228 self.assertRaises(TypeError, c.min_mag, 1, '2')
3229
3230 def test_minus(self):
3231 Decimal = self.decimal.Decimal
3232 Context = self.decimal.Context
3233
3234 c = Context()
3235 d = c.minus(Decimal(10))
3236 self.assertEqual(c.minus(10), d)
3237 self.assertRaises(TypeError, c.minus, '10')
3238
3239 def test_multiply(self):
3240 Decimal = self.decimal.Decimal
3241 Context = self.decimal.Context
3242
3243 c = Context()
3244 d = c.multiply(Decimal(1), Decimal(2))
3245 self.assertEqual(c.multiply(1, 2), d)
3246 self.assertEqual(c.multiply(Decimal(1), 2), d)
3247 self.assertEqual(c.multiply(1, Decimal(2)), d)
3248 self.assertRaises(TypeError, c.multiply, '1', 2)
3249 self.assertRaises(TypeError, c.multiply, 1, '2')
3250
3251 def test_next_minus(self):
3252 Decimal = self.decimal.Decimal
3253 Context = self.decimal.Context
3254
3255 c = Context()
3256 d = c.next_minus(Decimal(10))
3257 self.assertEqual(c.next_minus(10), d)
3258 self.assertRaises(TypeError, c.next_minus, '10')
3259
3260 def test_next_plus(self):
3261 Decimal = self.decimal.Decimal
3262 Context = self.decimal.Context
3263
3264 c = Context()
3265 d = c.next_plus(Decimal(10))
3266 self.assertEqual(c.next_plus(10), d)
3267 self.assertRaises(TypeError, c.next_plus, '10')
3268
3269 def test_next_toward(self):
3270 Decimal = self.decimal.Decimal
3271 Context = self.decimal.Context
3272
3273 c = Context()
3274 d = c.next_toward(Decimal(1), Decimal(2))
3275 self.assertEqual(c.next_toward(1, 2), d)
3276 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3277 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3278 self.assertRaises(TypeError, c.next_toward, '1', 2)
3279 self.assertRaises(TypeError, c.next_toward, 1, '2')
3280
3281 def test_normalize(self):
3282 Decimal = self.decimal.Decimal
3283 Context = self.decimal.Context
3284
3285 c = Context()
3286 d = c.normalize(Decimal(10))
3287 self.assertEqual(c.normalize(10), d)
3288 self.assertRaises(TypeError, c.normalize, '10')
3289
3290 def test_number_class(self):
3291 Decimal = self.decimal.Decimal
3292 Context = self.decimal.Context
3293
3294 c = Context()
3295 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3296 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3297 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3298
3299 def test_plus(self):
3300 Decimal = self.decimal.Decimal
3301 Context = self.decimal.Context
3302
3303 c = Context()
3304 d = c.plus(Decimal(10))
3305 self.assertEqual(c.plus(10), d)
3306 self.assertRaises(TypeError, c.plus, '10')
3307
3308 def test_power(self):
3309 Decimal = self.decimal.Decimal
3310 Context = self.decimal.Context
3311
3312 c = Context()
3313 d = c.power(Decimal(1), Decimal(4))
3314 self.assertEqual(c.power(1, 4), d)
3315 self.assertEqual(c.power(Decimal(1), 4), d)
3316 self.assertEqual(c.power(1, Decimal(4)), d)
3317 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3318 self.assertRaises(TypeError, c.power, '1', 4)
3319 self.assertRaises(TypeError, c.power, 1, '4')
3320 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3321
3322 def test_quantize(self):
3323 Decimal = self.decimal.Decimal
3324 Context = self.decimal.Context
3325
3326 c = Context()
3327 d = c.quantize(Decimal(1), Decimal(2))
3328 self.assertEqual(c.quantize(1, 2), d)
3329 self.assertEqual(c.quantize(Decimal(1), 2), d)
3330 self.assertEqual(c.quantize(1, Decimal(2)), d)
3331 self.assertRaises(TypeError, c.quantize, '1', 2)
3332 self.assertRaises(TypeError, c.quantize, 1, '2')
3333
3334 def test_remainder(self):
3335 Decimal = self.decimal.Decimal
3336 Context = self.decimal.Context
3337
3338 c = Context()
3339 d = c.remainder(Decimal(1), Decimal(2))
3340 self.assertEqual(c.remainder(1, 2), d)
3341 self.assertEqual(c.remainder(Decimal(1), 2), d)
3342 self.assertEqual(c.remainder(1, Decimal(2)), d)
3343 self.assertRaises(TypeError, c.remainder, '1', 2)
3344 self.assertRaises(TypeError, c.remainder, 1, '2')
3345
3346 def test_remainder_near(self):
3347 Decimal = self.decimal.Decimal
3348 Context = self.decimal.Context
3349
3350 c = Context()
3351 d = c.remainder_near(Decimal(1), Decimal(2))
3352 self.assertEqual(c.remainder_near(1, 2), d)
3353 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3354 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3355 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3356 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3357
3358 def test_rotate(self):
3359 Decimal = self.decimal.Decimal
3360 Context = self.decimal.Context
3361
3362 c = Context()
3363 d = c.rotate(Decimal(1), Decimal(2))
3364 self.assertEqual(c.rotate(1, 2), d)
3365 self.assertEqual(c.rotate(Decimal(1), 2), d)
3366 self.assertEqual(c.rotate(1, Decimal(2)), d)
3367 self.assertRaises(TypeError, c.rotate, '1', 2)
3368 self.assertRaises(TypeError, c.rotate, 1, '2')
3369
3370 def test_sqrt(self):
3371 Decimal = self.decimal.Decimal
3372 Context = self.decimal.Context
3373
3374 c = Context()
3375 d = c.sqrt(Decimal(10))
3376 self.assertEqual(c.sqrt(10), d)
3377 self.assertRaises(TypeError, c.sqrt, '10')
3378
3379 def test_same_quantum(self):
3380 Decimal = self.decimal.Decimal
3381 Context = self.decimal.Context
3382
3383 c = Context()
3384 d = c.same_quantum(Decimal(1), Decimal(2))
3385 self.assertEqual(c.same_quantum(1, 2), d)
3386 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3387 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3388 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3389 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3390
3391 def test_scaleb(self):
3392 Decimal = self.decimal.Decimal
3393 Context = self.decimal.Context
3394
3395 c = Context()
3396 d = c.scaleb(Decimal(1), Decimal(2))
3397 self.assertEqual(c.scaleb(1, 2), d)
3398 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3399 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3400 self.assertRaises(TypeError, c.scaleb, '1', 2)
3401 self.assertRaises(TypeError, c.scaleb, 1, '2')
3402
3403 def test_shift(self):
3404 Decimal = self.decimal.Decimal
3405 Context = self.decimal.Context
3406
3407 c = Context()
3408 d = c.shift(Decimal(1), Decimal(2))
3409 self.assertEqual(c.shift(1, 2), d)
3410 self.assertEqual(c.shift(Decimal(1), 2), d)
3411 self.assertEqual(c.shift(1, Decimal(2)), d)
3412 self.assertRaises(TypeError, c.shift, '1', 2)
3413 self.assertRaises(TypeError, c.shift, 1, '2')
3414
3415 def test_subtract(self):
3416 Decimal = self.decimal.Decimal
3417 Context = self.decimal.Context
3418
3419 c = Context()
3420 d = c.subtract(Decimal(1), Decimal(2))
3421 self.assertEqual(c.subtract(1, 2), d)
3422 self.assertEqual(c.subtract(Decimal(1), 2), d)
3423 self.assertEqual(c.subtract(1, Decimal(2)), d)
3424 self.assertRaises(TypeError, c.subtract, '1', 2)
3425 self.assertRaises(TypeError, c.subtract, 1, '2')
3426
3427 def test_to_eng_string(self):
3428 Decimal = self.decimal.Decimal
3429 Context = self.decimal.Context
3430
3431 c = Context()
3432 d = c.to_eng_string(Decimal(10))
3433 self.assertEqual(c.to_eng_string(10), d)
3434 self.assertRaises(TypeError, c.to_eng_string, '10')
3435
3436 def test_to_sci_string(self):
3437 Decimal = self.decimal.Decimal
3438 Context = self.decimal.Context
3439
3440 c = Context()
3441 d = c.to_sci_string(Decimal(10))
3442 self.assertEqual(c.to_sci_string(10), d)
3443 self.assertRaises(TypeError, c.to_sci_string, '10')
3444
3445 def test_to_integral_exact(self):
3446 Decimal = self.decimal.Decimal
3447 Context = self.decimal.Context
3448
3449 c = Context()
3450 d = c.to_integral_exact(Decimal(10))
3451 self.assertEqual(c.to_integral_exact(10), d)
3452 self.assertRaises(TypeError, c.to_integral_exact, '10')
3453
3454 def test_to_integral_value(self):
3455 Decimal = self.decimal.Decimal
3456 Context = self.decimal.Context
3457
3458 c = Context()
3459 d = c.to_integral_value(Decimal(10))
3460 self.assertEqual(c.to_integral_value(10), d)
3461 self.assertRaises(TypeError, c.to_integral_value, '10')
3462 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3463
3464class CContextAPItests(ContextAPItests):
3465 decimal = C
3466class PyContextAPItests(ContextAPItests):
3467 decimal = P
3468
3469class ContextWithStatement(unittest.TestCase):
3470 # Can't do these as docstrings until Python 2.6
3471 # as doctest can't handle __future__ statements
3472
3473 def test_localcontext(self):
3474 # Use a copy of the current context in the block
3475 getcontext = self.decimal.getcontext
3476 localcontext = self.decimal.localcontext
3477
3478 orig_ctx = getcontext()
3479 with localcontext() as enter_ctx:
3480 set_ctx = getcontext()
3481 final_ctx = getcontext()
3482 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3483 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3484 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3485
3486 def test_localcontextarg(self):
3487 # Use a copy of the supplied context in the block
3488 Context = self.decimal.Context
3489 getcontext = self.decimal.getcontext
3490 localcontext = self.decimal.localcontext
3491
3492 localcontext = self.decimal.localcontext
3493 orig_ctx = getcontext()
3494 new_ctx = Context(prec=42)
3495 with localcontext(new_ctx) as enter_ctx:
3496 set_ctx = getcontext()
3497 final_ctx = getcontext()
3498 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3499 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3500 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3501 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3502
3503 def test_nested_with_statements(self):
3504 # Use a copy of the supplied context in the block
3505 Decimal = self.decimal.Decimal
3506 Context = self.decimal.Context
3507 getcontext = self.decimal.getcontext
3508 localcontext = self.decimal.localcontext
3509 Clamped = self.decimal.Clamped
3510 Overflow = self.decimal.Overflow
3511
3512 orig_ctx = getcontext()
3513 orig_ctx.clear_flags()
3514 new_ctx = Context(Emax=384)
3515 with localcontext() as c1:
3516 self.assertEqual(c1.flags, orig_ctx.flags)
3517 self.assertEqual(c1.traps, orig_ctx.traps)
3518 c1.traps[Clamped] = True
3519 c1.Emin = -383
3520 self.assertNotEqual(orig_ctx.Emin, -383)
3521 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3522 self.assertTrue(c1.flags[Clamped])
3523 with localcontext(new_ctx) as c2:
3524 self.assertEqual(c2.flags, new_ctx.flags)
3525 self.assertEqual(c2.traps, new_ctx.traps)
3526 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3527 self.assertFalse(c2.flags[Clamped])
3528 self.assertTrue(c2.flags[Overflow])
3529 del c2
3530 self.assertFalse(c1.flags[Overflow])
3531 del c1
3532 self.assertNotEqual(orig_ctx.Emin, -383)
3533 self.assertFalse(orig_ctx.flags[Clamped])
3534 self.assertFalse(orig_ctx.flags[Overflow])
3535 self.assertFalse(new_ctx.flags[Clamped])
3536 self.assertFalse(new_ctx.flags[Overflow])
3537
3538 def test_with_statements_gc1(self):
3539 localcontext = self.decimal.localcontext
3540
3541 with localcontext() as c1:
3542 del c1
3543 with localcontext() as c2:
3544 del c2
3545 with localcontext() as c3:
3546 del c3
3547 with localcontext() as c4:
3548 del c4
3549
3550 def test_with_statements_gc2(self):
3551 localcontext = self.decimal.localcontext
3552
3553 with localcontext() as c1:
3554 with localcontext(c1) as c2:
3555 del c1
3556 with localcontext(c2) as c3:
3557 del c2
3558 with localcontext(c3) as c4:
3559 del c3
3560 del c4
3561
3562 def test_with_statements_gc3(self):
3563 Context = self.decimal.Context
3564 localcontext = self.decimal.localcontext
3565 getcontext = self.decimal.getcontext
3566 setcontext = self.decimal.setcontext
3567
3568 with localcontext() as c1:
3569 del c1
3570 n1 = Context(prec=1)
3571 setcontext(n1)
3572 with localcontext(n1) as c2:
3573 del n1
3574 self.assertEqual(c2.prec, 1)
3575 del c2
3576 n2 = Context(prec=2)
3577 setcontext(n2)
3578 del n2
3579 self.assertEqual(getcontext().prec, 2)
3580 n3 = Context(prec=3)
3581 setcontext(n3)
3582 self.assertEqual(getcontext().prec, 3)
3583 with localcontext(n3) as c3:
3584 del n3
3585 self.assertEqual(c3.prec, 3)
3586 del c3
3587 n4 = Context(prec=4)
3588 setcontext(n4)
3589 del n4
3590 self.assertEqual(getcontext().prec, 4)
3591 with localcontext() as c4:
3592 self.assertEqual(c4.prec, 4)
3593 del c4
3594
3595class CContextWithStatement(ContextWithStatement):
3596 decimal = C
3597class PyContextWithStatement(ContextWithStatement):
3598 decimal = P
3599
3600class ContextFlags(unittest.TestCase):
3601
3602 def test_flags_irrelevant(self):
3603 # check that the result (numeric result + flags raised) of an
3604 # arithmetic operation doesn't depend on the current flags
3605 Decimal = self.decimal.Decimal
3606 Context = self.decimal.Context
3607 Inexact = self.decimal.Inexact
3608 Rounded = self.decimal.Rounded
3609 Underflow = self.decimal.Underflow
3610 Clamped = self.decimal.Clamped
3611 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003612
3613 def raise_error(context, flag):
3614 if self.decimal == C:
3615 context.flags[flag] = True
3616 if context.traps[flag]:
3617 raise flag
3618 else:
3619 context._raise_error(flag)
3620
3621 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3622 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3623
3624 # operations that raise various flags, in the form (function, arglist)
3625 operations = [
3626 (context._apply, [Decimal("100E-425000010")]),
3627 (context.sqrt, [Decimal(2)]),
3628 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3629 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3630 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3631 ]
3632
3633 # try various flags individually, then a whole lot at once
3634 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3635 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3636
3637 for fn, args in operations:
3638 # find answer and flags raised using a clean context
3639 context.clear_flags()
3640 ans = fn(*args)
3641 flags = [k for k, v in context.flags.items() if v]
3642
3643 for extra_flags in flagsets:
3644 # set flags, before calling operation
3645 context.clear_flags()
3646 for flag in extra_flags:
3647 raise_error(context, flag)
3648 new_ans = fn(*args)
3649
3650 # flags that we expect to be set after the operation
3651 expected_flags = list(flags)
3652 for flag in extra_flags:
3653 if flag not in expected_flags:
3654 expected_flags.append(flag)
3655 expected_flags.sort(key=id)
3656
3657 # flags we actually got
3658 new_flags = [k for k,v in context.flags.items() if v]
3659 new_flags.sort(key=id)
3660
3661 self.assertEqual(ans, new_ans,
3662 "operation produces different answers depending on flags set: " +
3663 "expected %s, got %s." % (ans, new_ans))
3664 self.assertEqual(new_flags, expected_flags,
3665 "operation raises different flags depending on flags set: " +
3666 "expected %s, got %s" % (expected_flags, new_flags))
3667
3668 def test_flag_comparisons(self):
3669 Context = self.decimal.Context
3670 Inexact = self.decimal.Inexact
3671 Rounded = self.decimal.Rounded
3672
3673 c = Context()
3674
3675 # Valid SignalDict
3676 self.assertNotEqual(c.flags, c.traps)
3677 self.assertNotEqual(c.traps, c.flags)
3678
3679 c.flags = c.traps
3680 self.assertEqual(c.flags, c.traps)
3681 self.assertEqual(c.traps, c.flags)
3682
3683 c.flags[Rounded] = True
3684 c.traps = c.flags
3685 self.assertEqual(c.flags, c.traps)
3686 self.assertEqual(c.traps, c.flags)
3687
3688 d = {}
3689 d.update(c.flags)
3690 self.assertEqual(d, c.flags)
3691 self.assertEqual(c.flags, d)
3692
3693 d[Inexact] = True
3694 self.assertNotEqual(d, c.flags)
3695 self.assertNotEqual(c.flags, d)
3696
3697 # Invalid SignalDict
3698 d = {Inexact:False}
3699 self.assertNotEqual(d, c.flags)
3700 self.assertNotEqual(c.flags, d)
3701
3702 d = ["xyz"]
3703 self.assertNotEqual(d, c.flags)
3704 self.assertNotEqual(c.flags, d)
3705
3706 @requires_IEEE_754
3707 def test_float_operation(self):
3708 Decimal = self.decimal.Decimal
3709 FloatOperation = self.decimal.FloatOperation
3710 localcontext = self.decimal.localcontext
3711
3712 with localcontext() as c:
3713 ##### trap is off by default
3714 self.assertFalse(c.traps[FloatOperation])
3715
3716 # implicit conversion sets the flag
3717 c.clear_flags()
3718 self.assertEqual(Decimal(7.5), 7.5)
3719 self.assertTrue(c.flags[FloatOperation])
3720
3721 c.clear_flags()
3722 self.assertEqual(c.create_decimal(7.5), 7.5)
3723 self.assertTrue(c.flags[FloatOperation])
3724
3725 # explicit conversion does not set the flag
3726 c.clear_flags()
3727 x = Decimal.from_float(7.5)
3728 self.assertFalse(c.flags[FloatOperation])
3729 # comparison sets the flag
3730 self.assertEqual(x, 7.5)
3731 self.assertTrue(c.flags[FloatOperation])
3732
3733 c.clear_flags()
3734 x = c.create_decimal_from_float(7.5)
3735 self.assertFalse(c.flags[FloatOperation])
3736 self.assertEqual(x, 7.5)
3737 self.assertTrue(c.flags[FloatOperation])
3738
3739 ##### set the trap
3740 c.traps[FloatOperation] = True
3741
3742 # implicit conversion raises
3743 c.clear_flags()
3744 self.assertRaises(FloatOperation, Decimal, 7.5)
3745 self.assertTrue(c.flags[FloatOperation])
3746
3747 c.clear_flags()
3748 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3749 self.assertTrue(c.flags[FloatOperation])
3750
3751 # explicit conversion is silent
3752 c.clear_flags()
3753 x = Decimal.from_float(7.5)
3754 self.assertFalse(c.flags[FloatOperation])
3755
3756 c.clear_flags()
3757 x = c.create_decimal_from_float(7.5)
3758 self.assertFalse(c.flags[FloatOperation])
3759
3760 def test_float_comparison(self):
3761 Decimal = self.decimal.Decimal
3762 Context = self.decimal.Context
3763 FloatOperation = self.decimal.FloatOperation
3764 localcontext = self.decimal.localcontext
3765
3766 def assert_attr(a, b, attr, context, signal=None):
3767 context.clear_flags()
3768 f = getattr(a, attr)
3769 if signal == FloatOperation:
3770 self.assertRaises(signal, f, b)
3771 else:
3772 self.assertIs(f(b), True)
3773 self.assertTrue(context.flags[FloatOperation])
3774
3775 small_d = Decimal('0.25')
3776 big_d = Decimal('3.0')
3777 small_f = 0.25
3778 big_f = 3.0
3779
3780 zero_d = Decimal('0.0')
3781 neg_zero_d = Decimal('-0.0')
3782 zero_f = 0.0
3783 neg_zero_f = -0.0
3784
3785 inf_d = Decimal('Infinity')
3786 neg_inf_d = Decimal('-Infinity')
3787 inf_f = float('inf')
3788 neg_inf_f = float('-inf')
3789
3790 def doit(c, signal=None):
3791 # Order
3792 for attr in '__lt__', '__le__':
3793 assert_attr(small_d, big_f, attr, c, signal)
3794
3795 for attr in '__gt__', '__ge__':
3796 assert_attr(big_d, small_f, attr, c, signal)
3797
3798 # Equality
3799 assert_attr(small_d, small_f, '__eq__', c, None)
3800
3801 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3802 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3803
3804 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3805 assert_attr(zero_d, zero_f, '__eq__', c, None)
3806
3807 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3808 assert_attr(inf_d, inf_f, '__eq__', c, None)
3809
3810 # Inequality
3811 assert_attr(small_d, big_f, '__ne__', c, None)
3812
3813 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3814
3815 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3816 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3817
3818 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3819
3820 def test_containers(c, signal=None):
3821 c.clear_flags()
3822 s = set([100.0, Decimal('100.0')])
3823 self.assertEqual(len(s), 1)
3824 self.assertTrue(c.flags[FloatOperation])
3825
3826 c.clear_flags()
3827 if signal:
3828 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3829 else:
3830 s = sorted([10.0, Decimal('10.0')])
3831 self.assertTrue(c.flags[FloatOperation])
3832
3833 c.clear_flags()
3834 b = 10.0 in [Decimal('10.0'), 1.0]
3835 self.assertTrue(c.flags[FloatOperation])
3836
3837 c.clear_flags()
3838 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3839 self.assertTrue(c.flags[FloatOperation])
3840
3841 nc = Context()
3842 with localcontext(nc) as c:
3843 self.assertFalse(c.traps[FloatOperation])
3844 doit(c, signal=None)
3845 test_containers(c, signal=None)
3846
3847 c.traps[FloatOperation] = True
3848 doit(c, signal=FloatOperation)
3849 test_containers(c, signal=FloatOperation)
3850
3851 def test_float_operation_default(self):
3852 Decimal = self.decimal.Decimal
3853 Context = self.decimal.Context
3854 Inexact = self.decimal.Inexact
3855 FloatOperation= self.decimal.FloatOperation
3856
3857 context = Context()
3858 self.assertFalse(context.flags[FloatOperation])
3859 self.assertFalse(context.traps[FloatOperation])
3860
3861 context.clear_traps()
3862 context.traps[Inexact] = True
3863 context.traps[FloatOperation] = True
3864 self.assertTrue(context.traps[FloatOperation])
3865 self.assertTrue(context.traps[Inexact])
3866
3867class CContextFlags(ContextFlags):
3868 decimal = C
3869class PyContextFlags(ContextFlags):
3870 decimal = P
3871
3872class SpecialContexts(unittest.TestCase):
3873 """Test the context templates."""
3874
3875 def test_context_templates(self):
3876 BasicContext = self.decimal.BasicContext
3877 ExtendedContext = self.decimal.ExtendedContext
3878 getcontext = self.decimal.getcontext
3879 setcontext = self.decimal.setcontext
3880 InvalidOperation = self.decimal.InvalidOperation
3881 DivisionByZero = self.decimal.DivisionByZero
3882 Overflow = self.decimal.Overflow
3883 Underflow = self.decimal.Underflow
3884 Clamped = self.decimal.Clamped
3885
3886 assert_signals(self, BasicContext, 'traps',
3887 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3888 )
3889
3890 savecontext = getcontext().copy()
3891 basic_context_prec = BasicContext.prec
3892 extended_context_prec = ExtendedContext.prec
3893
3894 ex = None
3895 try:
3896 BasicContext.prec = ExtendedContext.prec = 441
3897 for template in BasicContext, ExtendedContext:
3898 setcontext(template)
3899 c = getcontext()
3900 self.assertIsNot(c, template)
3901 self.assertEqual(c.prec, 441)
3902 except Exception as e:
3903 ex = e.__class__
3904 finally:
3905 BasicContext.prec = basic_context_prec
3906 ExtendedContext.prec = extended_context_prec
3907 setcontext(savecontext)
3908 if ex:
3909 raise ex
3910
3911 def test_default_context(self):
3912 DefaultContext = self.decimal.DefaultContext
3913 BasicContext = self.decimal.BasicContext
3914 ExtendedContext = self.decimal.ExtendedContext
3915 getcontext = self.decimal.getcontext
3916 setcontext = self.decimal.setcontext
3917 InvalidOperation = self.decimal.InvalidOperation
3918 DivisionByZero = self.decimal.DivisionByZero
3919 Overflow = self.decimal.Overflow
3920
3921 self.assertEqual(BasicContext.prec, 9)
3922 self.assertEqual(ExtendedContext.prec, 9)
3923
3924 assert_signals(self, DefaultContext, 'traps',
3925 [InvalidOperation, DivisionByZero, Overflow]
3926 )
3927
3928 savecontext = getcontext().copy()
3929 default_context_prec = DefaultContext.prec
3930
3931 ex = None
3932 try:
3933 c = getcontext()
3934 saveprec = c.prec
3935
3936 DefaultContext.prec = 961
3937 c = getcontext()
3938 self.assertEqual(c.prec, saveprec)
3939
3940 setcontext(DefaultContext)
3941 c = getcontext()
3942 self.assertIsNot(c, DefaultContext)
3943 self.assertEqual(c.prec, 961)
3944 except Exception as e:
3945 ex = e.__class__
3946 finally:
3947 DefaultContext.prec = default_context_prec
3948 setcontext(savecontext)
3949 if ex:
3950 raise ex
3951
3952class CSpecialContexts(SpecialContexts):
3953 decimal = C
3954class PySpecialContexts(SpecialContexts):
3955 decimal = P
3956
3957class ContextInputValidation(unittest.TestCase):
3958
3959 def test_invalid_context(self):
3960 Context = self.decimal.Context
3961 DefaultContext = self.decimal.DefaultContext
3962
3963 c = DefaultContext.copy()
3964
3965 # prec, Emax
3966 for attr in ['prec', 'Emax']:
3967 setattr(c, attr, 999999)
3968 self.assertEqual(getattr(c, attr), 999999)
3969 self.assertRaises(ValueError, setattr, c, attr, -1)
3970 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3971
3972 # Emin
3973 setattr(c, 'Emin', -999999)
3974 self.assertEqual(getattr(c, 'Emin'), -999999)
3975 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3976 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3977
Stefan Krah1919b7e2012-03-21 18:25:23 +01003978 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3979 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3980 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3981 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3982
3983 # capitals, clamp
3984 for attr in ['capitals', 'clamp']:
3985 self.assertRaises(ValueError, setattr, c, attr, -1)
3986 self.assertRaises(ValueError, setattr, c, attr, 2)
3987 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3988
3989 # Invalid attribute
3990 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3991
3992 # Invalid signal dict
3993 self.assertRaises(TypeError, setattr, c, 'flags', [])
3994 self.assertRaises(KeyError, setattr, c, 'flags', {})
3995 self.assertRaises(KeyError, setattr, c, 'traps',
3996 {'InvalidOperation':0})
3997
3998 # Attributes cannot be deleted
3999 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4000 'flags', 'traps']:
4001 self.assertRaises(AttributeError, c.__delattr__, attr)
4002
4003 # Invalid attributes
4004 self.assertRaises(TypeError, getattr, c, 9)
4005 self.assertRaises(TypeError, setattr, c, 9)
4006
4007 # Invalid values in constructor
4008 self.assertRaises(TypeError, Context, rounding=999999)
4009 self.assertRaises(TypeError, Context, rounding='xyz')
4010 self.assertRaises(ValueError, Context, clamp=2)
4011 self.assertRaises(ValueError, Context, capitals=-1)
4012 self.assertRaises(KeyError, Context, flags=["P"])
4013 self.assertRaises(KeyError, Context, traps=["Q"])
4014
4015 # Type error in conversion
4016 self.assertRaises(TypeError, Context, flags=(0,1))
4017 self.assertRaises(TypeError, Context, traps=(1,0))
4018
4019class CContextInputValidation(ContextInputValidation):
4020 decimal = C
4021class PyContextInputValidation(ContextInputValidation):
4022 decimal = P
4023
4024class ContextSubclassing(unittest.TestCase):
4025
4026 def test_context_subclassing(self):
4027 decimal = self.decimal
4028 Decimal = decimal.Decimal
4029 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004030 Clamped = decimal.Clamped
4031 DivisionByZero = decimal.DivisionByZero
4032 Inexact = decimal.Inexact
4033 Overflow = decimal.Overflow
4034 Rounded = decimal.Rounded
4035 Subnormal = decimal.Subnormal
4036 Underflow = decimal.Underflow
4037 InvalidOperation = decimal.InvalidOperation
4038
4039 class MyContext(Context):
4040 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4041 capitals=None, clamp=None, flags=None,
4042 traps=None):
4043 Context.__init__(self)
4044 if prec is not None:
4045 self.prec = prec
4046 if rounding is not None:
4047 self.rounding = rounding
4048 if Emin is not None:
4049 self.Emin = Emin
4050 if Emax is not None:
4051 self.Emax = Emax
4052 if capitals is not None:
4053 self.capitals = capitals
4054 if clamp is not None:
4055 self.clamp = clamp
4056 if flags is not None:
4057 if isinstance(flags, list):
4058 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4059 self.flags = flags
4060 if traps is not None:
4061 if isinstance(traps, list):
4062 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4063 self.traps = traps
4064
4065 c = Context()
4066 d = MyContext()
4067 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4068 'flags', 'traps'):
4069 self.assertEqual(getattr(c, attr), getattr(d, attr))
4070
4071 # prec
4072 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4073 c = MyContext(prec=1)
4074 self.assertEqual(c.prec, 1)
4075 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4076
4077 # rounding
4078 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4079 c = MyContext(rounding=ROUND_DOWN, prec=1)
4080 self.assertEqual(c.rounding, ROUND_DOWN)
4081 self.assertEqual(c.plus(Decimal('9.9')), 9)
4082
4083 # Emin
4084 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4085 c = MyContext(Emin=-1, prec=1)
4086 self.assertEqual(c.Emin, -1)
4087 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4088 self.assertEqual(x, Decimal('0.0'))
4089 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4090 self.assertTrue(c.flags[signal])
4091
4092 # Emax
4093 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4094 c = MyContext(Emax=1, prec=1)
4095 self.assertEqual(c.Emax, 1)
4096 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4097 if self.decimal == C:
4098 for signal in (Inexact, Overflow, Rounded):
4099 self.assertTrue(c.flags[signal])
4100
4101 # capitals
4102 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4103 c = MyContext(capitals=0)
4104 self.assertEqual(c.capitals, 0)
4105 x = c.create_decimal('1E222')
4106 self.assertEqual(c.to_sci_string(x), '1e+222')
4107
4108 # clamp
4109 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4110 c = MyContext(clamp=1, Emax=99)
4111 self.assertEqual(c.clamp, 1)
4112 x = c.plus(Decimal('1e99'))
4113 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4114
4115 # flags
4116 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4117 c = MyContext(flags=[Rounded, DivisionByZero])
4118 for signal in (Rounded, DivisionByZero):
4119 self.assertTrue(c.flags[signal])
4120 c.clear_flags()
4121 for signal in OrderedSignals[decimal]:
4122 self.assertFalse(c.flags[signal])
4123
4124 # traps
4125 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4126 c = MyContext(traps=[Rounded, DivisionByZero])
4127 for signal in (Rounded, DivisionByZero):
4128 self.assertTrue(c.traps[signal])
4129 c.clear_traps()
4130 for signal in OrderedSignals[decimal]:
4131 self.assertFalse(c.traps[signal])
4132
4133class CContextSubclassing(ContextSubclassing):
4134 decimal = C
4135class PyContextSubclassing(ContextSubclassing):
4136 decimal = P
4137
4138@skip_if_extra_functionality
4139class CheckAttributes(unittest.TestCase):
4140
4141 def test_module_attributes(self):
4142
4143 # Architecture dependent context limits
4144 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4145 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4146 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4147 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4148
4149 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4150 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4151
4152 self.assertEqual(C.__version__, P.__version__)
4153
4154 x = dir(C)
4155 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02004156 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004157
4158 def test_context_attributes(self):
4159
4160 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4161 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4162 self.assertEqual(set(x) - set(y), set())
4163
4164 def test_decimal_attributes(self):
4165
4166 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4167 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4168 self.assertEqual(set(x) - set(y), set())
4169
4170class Coverage(unittest.TestCase):
4171
4172 def test_adjusted(self):
4173 Decimal = self.decimal.Decimal
4174
4175 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4176 # XXX raise?
4177 self.assertEqual(Decimal('nan').adjusted(), 0)
4178 self.assertEqual(Decimal('inf').adjusted(), 0)
4179
4180 def test_canonical(self):
4181 Decimal = self.decimal.Decimal
4182 getcontext = self.decimal.getcontext
4183
4184 x = Decimal(9).canonical()
4185 self.assertEqual(x, 9)
4186
4187 c = getcontext()
4188 x = c.canonical(Decimal(9))
4189 self.assertEqual(x, 9)
4190
4191 def test_context_repr(self):
4192 c = self.decimal.DefaultContext.copy()
4193
4194 c.prec = 425000000
4195 c.Emax = 425000000
4196 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004197 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004198 c.capitals = 0
4199 c.clamp = 1
4200 for sig in OrderedSignals[self.decimal]:
4201 c.flags[sig] = False
4202 c.traps[sig] = False
4203
4204 s = c.__repr__()
4205 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4206 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4207 "flags=[], traps=[])"
4208 self.assertEqual(s, t)
4209
4210 def test_implicit_context(self):
4211 Decimal = self.decimal.Decimal
4212 localcontext = self.decimal.localcontext
4213
4214 with localcontext() as c:
4215 c.prec = 1
4216 c.Emax = 1
4217 c.Emin = -1
4218
4219 # abs
4220 self.assertEqual(abs(Decimal("-10")), 10)
4221 # add
4222 self.assertEqual(Decimal("7") + 1, 8)
4223 # divide
4224 self.assertEqual(Decimal("10") / 5, 2)
4225 # divide_int
4226 self.assertEqual(Decimal("10") // 7, 1)
4227 # fma
4228 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4229 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4230 # three arg power
4231 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4232 # exp
4233 self.assertEqual(Decimal("1.01").exp(), 3)
4234 # is_normal
4235 self.assertIs(Decimal("0.01").is_normal(), False)
4236 # is_subnormal
4237 self.assertIs(Decimal("0.01").is_subnormal(), True)
4238 # ln
4239 self.assertEqual(Decimal("20").ln(), 3)
4240 # log10
4241 self.assertEqual(Decimal("20").log10(), 1)
4242 # logb
4243 self.assertEqual(Decimal("580").logb(), 2)
4244 # logical_invert
4245 self.assertEqual(Decimal("10").logical_invert(), 1)
4246 # minus
4247 self.assertEqual(-Decimal("-10"), 10)
4248 # multiply
4249 self.assertEqual(Decimal("2") * 4, 8)
4250 # next_minus
4251 self.assertEqual(Decimal("10").next_minus(), 9)
4252 # next_plus
4253 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4254 # normalize
4255 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4256 # number_class
4257 self.assertEqual(Decimal("10").number_class(), '+Normal')
4258 # plus
4259 self.assertEqual(+Decimal("-1"), -1)
4260 # remainder
4261 self.assertEqual(Decimal("10") % 7, 3)
4262 # subtract
4263 self.assertEqual(Decimal("10") - 7, 3)
4264 # to_integral_exact
4265 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4266
4267 # Boolean functions
4268 self.assertTrue(Decimal("1").is_canonical())
4269 self.assertTrue(Decimal("1").is_finite())
4270 self.assertTrue(Decimal("1").is_finite())
4271 self.assertTrue(Decimal("snan").is_snan())
4272 self.assertTrue(Decimal("-1").is_signed())
4273 self.assertTrue(Decimal("0").is_zero())
4274 self.assertTrue(Decimal("0").is_zero())
4275
4276 # Copy
4277 with localcontext() as c:
4278 c.prec = 10000
4279 x = 1228 ** 1523
4280 y = -Decimal(x)
4281
4282 z = y.copy_abs()
4283 self.assertEqual(z, x)
4284
4285 z = y.copy_negate()
4286 self.assertEqual(z, x)
4287
4288 z = y.copy_sign(Decimal(1))
4289 self.assertEqual(z, x)
4290
4291 def test_divmod(self):
4292 Decimal = self.decimal.Decimal
4293 localcontext = self.decimal.localcontext
4294 InvalidOperation = self.decimal.InvalidOperation
4295 DivisionByZero = self.decimal.DivisionByZero
4296
4297 with localcontext() as c:
4298 q, r = divmod(Decimal("10912837129"), 1001)
4299 self.assertEqual(q, Decimal('10901935'))
4300 self.assertEqual(r, Decimal('194'))
4301
4302 q, r = divmod(Decimal("NaN"), 7)
4303 self.assertTrue(q.is_nan() and r.is_nan())
4304
4305 c.traps[InvalidOperation] = False
4306 q, r = divmod(Decimal("NaN"), 7)
4307 self.assertTrue(q.is_nan() and r.is_nan())
4308
4309 c.traps[InvalidOperation] = False
4310 c.clear_flags()
4311 q, r = divmod(Decimal("inf"), Decimal("inf"))
4312 self.assertTrue(q.is_nan() and r.is_nan())
4313 self.assertTrue(c.flags[InvalidOperation])
4314
4315 c.clear_flags()
4316 q, r = divmod(Decimal("inf"), 101)
4317 self.assertTrue(q.is_infinite() and r.is_nan())
4318 self.assertTrue(c.flags[InvalidOperation])
4319
4320 c.clear_flags()
4321 q, r = divmod(Decimal(0), 0)
4322 self.assertTrue(q.is_nan() and r.is_nan())
4323 self.assertTrue(c.flags[InvalidOperation])
4324
4325 c.traps[DivisionByZero] = False
4326 c.clear_flags()
4327 q, r = divmod(Decimal(11), 0)
4328 self.assertTrue(q.is_infinite() and r.is_nan())
4329 self.assertTrue(c.flags[InvalidOperation] and
4330 c.flags[DivisionByZero])
4331
4332 def test_power(self):
4333 Decimal = self.decimal.Decimal
4334 localcontext = self.decimal.localcontext
4335 Overflow = self.decimal.Overflow
4336 Rounded = self.decimal.Rounded
4337
4338 with localcontext() as c:
4339 c.prec = 3
4340 c.clear_flags()
4341 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4342 self.assertTrue(c.flags[Rounded])
4343
4344 c.prec = 1
4345 c.Emax = 1
4346 c.Emin = -1
4347 c.clear_flags()
4348 c.traps[Overflow] = False
4349 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4350 self.assertTrue(c.flags[Overflow])
4351
4352 def test_quantize(self):
4353 Decimal = self.decimal.Decimal
4354 localcontext = self.decimal.localcontext
4355 InvalidOperation = self.decimal.InvalidOperation
4356
4357 with localcontext() as c:
4358 c.prec = 1
4359 c.Emax = 1
4360 c.Emin = -1
4361 c.traps[InvalidOperation] = False
4362 x = Decimal(99).quantize(Decimal("1e1"))
4363 self.assertTrue(x.is_nan())
4364
4365 def test_radix(self):
4366 Decimal = self.decimal.Decimal
4367 getcontext = self.decimal.getcontext
4368
4369 c = getcontext()
4370 self.assertEqual(Decimal("1").radix(), 10)
4371 self.assertEqual(c.radix(), 10)
4372
4373 def test_rop(self):
4374 Decimal = self.decimal.Decimal
4375
4376 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4377 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4378 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4379
4380 def test_round(self):
4381 # Python3 behavior: round() returns Decimal
4382 Decimal = self.decimal.Decimal
4383 getcontext = self.decimal.getcontext
4384
4385 c = getcontext()
4386 c.prec = 28
4387
4388 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4389 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4390 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4391 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4392 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4393
4394 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4395 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4396
4397 def test_create_decimal(self):
4398 c = self.decimal.Context()
4399 self.assertRaises(ValueError, c.create_decimal, ["%"])
4400
4401 def test_int(self):
4402 Decimal = self.decimal.Decimal
4403 localcontext = self.decimal.localcontext
4404
4405 with localcontext() as c:
4406 c.prec = 9999
4407 x = Decimal(1221**1271) / 10**3923
4408 self.assertEqual(int(x), 1)
4409 self.assertEqual(x.to_integral(), 2)
4410
4411 def test_copy(self):
4412 Context = self.decimal.Context
4413
4414 c = Context()
4415 c.prec = 10000
4416 x = -(1172 ** 1712)
4417
4418 y = c.copy_abs(x)
4419 self.assertEqual(y, -x)
4420
4421 y = c.copy_negate(x)
4422 self.assertEqual(y, -x)
4423
4424 y = c.copy_sign(x, 1)
4425 self.assertEqual(y, -x)
4426
4427class CCoverage(Coverage):
4428 decimal = C
4429class PyCoverage(Coverage):
4430 decimal = P
4431
4432class PyFunctionality(unittest.TestCase):
4433 """Extra functionality in decimal.py"""
4434
4435 def test_py_quantize_watchexp(self):
4436 # watchexp functionality
4437 Decimal = P.Decimal
4438 localcontext = P.localcontext
4439
4440 with localcontext() as c:
4441 c.prec = 1
4442 c.Emax = 1
4443 c.Emin = -1
4444 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4445 self.assertEqual(x, Decimal('1.00E+5'))
4446
4447 def test_py_alternate_formatting(self):
4448 # triples giving a format, a Decimal, and the expected result
4449 Decimal = P.Decimal
4450 localcontext = P.localcontext
4451
4452 test_values = [
4453 # Issue 7094: Alternate formatting (specified by #)
4454 ('.0e', '1.0', '1e+0'),
4455 ('#.0e', '1.0', '1.e+0'),
4456 ('.0f', '1.0', '1'),
4457 ('#.0f', '1.0', '1.'),
4458 ('g', '1.1', '1.1'),
4459 ('#g', '1.1', '1.1'),
4460 ('.0g', '1', '1'),
4461 ('#.0g', '1', '1.'),
4462 ('.0%', '1.0', '100%'),
4463 ('#.0%', '1.0', '100.%'),
4464 ]
4465 for fmt, d, result in test_values:
4466 self.assertEqual(format(Decimal(d), fmt), result)
4467
4468class PyWhitebox(unittest.TestCase):
4469 """White box testing for decimal.py"""
4470
4471 def test_py_exact_power(self):
4472 # Rarely exercised lines in _power_exact.
4473 Decimal = P.Decimal
4474 localcontext = P.localcontext
4475
4476 with localcontext() as c:
4477 c.prec = 8
4478 x = Decimal(2**16) ** Decimal("-0.5")
4479 self.assertEqual(x, Decimal('0.00390625'))
4480
4481 x = Decimal(2**16) ** Decimal("-0.6")
4482 self.assertEqual(x, Decimal('0.0012885819'))
4483
4484 x = Decimal("256e7") ** Decimal("-0.5")
4485
4486 x = Decimal(152587890625) ** Decimal('-0.0625')
4487 self.assertEqual(x, Decimal("0.2"))
4488
4489 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4490
4491 x = Decimal(5**2659) ** Decimal('-0.0625')
4492
4493 c.prec = 1
4494 x = Decimal("152587890625") ** Decimal('-0.5')
4495 c.prec = 201
4496 x = Decimal(2**578) ** Decimal("-0.5")
4497
4498 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004499 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004500 Decimal = P.Decimal
4501 DefaultContext = P.DefaultContext
4502 setcontext = P.setcontext
4503
4504 c = DefaultContext.copy()
4505 c.traps = dict((s, 0) for s in OrderedSignals[P])
4506 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004507
4508 d1 = Decimal('-25e55')
4509 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004510 d2 = Decimal('33e+33')
4511 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004512
4513 def checkSameDec(operation, useOther=False):
4514 if useOther:
4515 eval("d1." + operation + "(d2)")
4516 self.assertEqual(d1._sign, b1._sign)
4517 self.assertEqual(d1._int, b1._int)
4518 self.assertEqual(d1._exp, b1._exp)
4519 self.assertEqual(d2._sign, b2._sign)
4520 self.assertEqual(d2._int, b2._int)
4521 self.assertEqual(d2._exp, b2._exp)
4522 else:
4523 eval("d1." + operation + "()")
4524 self.assertEqual(d1._sign, b1._sign)
4525 self.assertEqual(d1._int, b1._int)
4526 self.assertEqual(d1._exp, b1._exp)
4527 return
4528
4529 Decimal(d1)
4530 self.assertEqual(d1._sign, b1._sign)
4531 self.assertEqual(d1._int, b1._int)
4532 self.assertEqual(d1._exp, b1._exp)
4533
4534 checkSameDec("__abs__")
4535 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004536 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004537 checkSameDec("__eq__", True)
4538 checkSameDec("__ne__", True)
4539 checkSameDec("__le__", True)
4540 checkSameDec("__lt__", True)
4541 checkSameDec("__ge__", True)
4542 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004543 checkSameDec("__float__")
4544 checkSameDec("__floordiv__", True)
4545 checkSameDec("__hash__")
4546 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004547 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004548 checkSameDec("__mod__", True)
4549 checkSameDec("__mul__", True)
4550 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004551 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004552 checkSameDec("__pos__")
4553 checkSameDec("__pow__", True)
4554 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004555 checkSameDec("__rdivmod__", True)
4556 checkSameDec("__repr__")
4557 checkSameDec("__rfloordiv__", True)
4558 checkSameDec("__rmod__", True)
4559 checkSameDec("__rmul__", True)
4560 checkSameDec("__rpow__", True)
4561 checkSameDec("__rsub__", True)
4562 checkSameDec("__str__")
4563 checkSameDec("__sub__", True)
4564 checkSameDec("__truediv__", True)
4565 checkSameDec("adjusted")
4566 checkSameDec("as_tuple")
4567 checkSameDec("compare", True)
4568 checkSameDec("max", True)
4569 checkSameDec("min", True)
4570 checkSameDec("normalize")
4571 checkSameDec("quantize", True)
4572 checkSameDec("remainder_near", True)
4573 checkSameDec("same_quantum", True)
4574 checkSameDec("sqrt")
4575 checkSameDec("to_eng_string")
4576 checkSameDec("to_integral")
4577
Stefan Krah1919b7e2012-03-21 18:25:23 +01004578 def test_py_decimal_id(self):
4579 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004580
Stefan Krah1919b7e2012-03-21 18:25:23 +01004581 d = Decimal(45)
4582 e = Decimal(d)
4583 self.assertEqual(str(e), '45')
4584 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004585
Stefan Krah1919b7e2012-03-21 18:25:23 +01004586 def test_py_rescale(self):
4587 # Coverage
4588 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004589 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004590
Stefan Krah1919b7e2012-03-21 18:25:23 +01004591 with localcontext() as c:
4592 x = Decimal("NaN")._rescale(3, ROUND_UP)
4593 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004594
Stefan Krah1919b7e2012-03-21 18:25:23 +01004595 def test_py__round(self):
4596 # Coverage
4597 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004598
Stefan Krah1919b7e2012-03-21 18:25:23 +01004599 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004600
Stefan Krah1919b7e2012-03-21 18:25:23 +01004601class CFunctionality(unittest.TestCase):
4602 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004603
Stefan Krah1919b7e2012-03-21 18:25:23 +01004604 @requires_extra_functionality
4605 def test_c_ieee_context(self):
4606 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4607 IEEEContext = C.IEEEContext
4608 DECIMAL32 = C.DECIMAL32
4609 DECIMAL64 = C.DECIMAL64
4610 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004611
Stefan Krah1919b7e2012-03-21 18:25:23 +01004612 def assert_rest(self, context):
4613 self.assertEqual(context.clamp, 1)
4614 assert_signals(self, context, 'traps', [])
4615 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004616
Stefan Krah1919b7e2012-03-21 18:25:23 +01004617 c = IEEEContext(DECIMAL32)
4618 self.assertEqual(c.prec, 7)
4619 self.assertEqual(c.Emax, 96)
4620 self.assertEqual(c.Emin, -95)
4621 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004622
Stefan Krah1919b7e2012-03-21 18:25:23 +01004623 c = IEEEContext(DECIMAL64)
4624 self.assertEqual(c.prec, 16)
4625 self.assertEqual(c.Emax, 384)
4626 self.assertEqual(c.Emin, -383)
4627 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004628
Stefan Krah1919b7e2012-03-21 18:25:23 +01004629 c = IEEEContext(DECIMAL128)
4630 self.assertEqual(c.prec, 34)
4631 self.assertEqual(c.Emax, 6144)
4632 self.assertEqual(c.Emin, -6143)
4633 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004634
Stefan Krah1919b7e2012-03-21 18:25:23 +01004635 # Invalid values
4636 self.assertRaises(OverflowError, IEEEContext, 2**63)
4637 self.assertRaises(ValueError, IEEEContext, -1)
4638 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004639
Stefan Krah1919b7e2012-03-21 18:25:23 +01004640 @requires_extra_functionality
4641 def test_c_context(self):
4642 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004643
Stefan Krah1919b7e2012-03-21 18:25:23 +01004644 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4645 self.assertEqual(c._flags, C.DecClamped)
4646 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004647
Stefan Krah1919b7e2012-03-21 18:25:23 +01004648 @requires_extra_functionality
4649 def test_constants(self):
4650 # Condition flags
4651 cond = (
4652 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4653 C.DecDivisionImpossible, C.DecDivisionUndefined,
4654 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4655 C.DecInvalidOperation, C.DecMallocError,
4656 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4657 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004658 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004659
4660 # IEEEContext
4661 self.assertEqual(C.DECIMAL32, 32)
4662 self.assertEqual(C.DECIMAL64, 64)
4663 self.assertEqual(C.DECIMAL128, 128)
4664 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4665
Stefan Krah1919b7e2012-03-21 18:25:23 +01004666 # Conditions
4667 for i, v in enumerate(cond):
4668 self.assertEqual(v, 1<<i)
4669
4670 self.assertEqual(C.DecIEEEInvalidOperation,
4671 C.DecConversionSyntax|
4672 C.DecDivisionImpossible|
4673 C.DecDivisionUndefined|
4674 C.DecFpuError|
4675 C.DecInvalidContext|
4676 C.DecInvalidOperation|
4677 C.DecMallocError)
4678
4679 self.assertEqual(C.DecErrors,
4680 C.DecIEEEInvalidOperation|
4681 C.DecDivisionByZero)
4682
4683 self.assertEqual(C.DecTraps,
4684 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4685
4686class CWhitebox(unittest.TestCase):
4687 """Whitebox testing for _decimal"""
4688
4689 def test_bignum(self):
4690 # Not exactly whitebox, but too slow with pydecimal.
4691
4692 Decimal = C.Decimal
4693 localcontext = C.localcontext
4694
4695 b1 = 10**35
4696 b2 = 10**36
4697 with localcontext() as c:
4698 c.prec = 1000000
4699 for i in range(5):
4700 a = random.randrange(b1, b2)
4701 b = random.randrange(1000, 1200)
4702 x = a ** b
4703 y = Decimal(a) ** Decimal(b)
4704 self.assertEqual(x, y)
4705
4706 def test_invalid_construction(self):
4707 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4708
4709 def test_c_input_restriction(self):
4710 # Too large for _decimal to be converted exactly
4711 Decimal = C.Decimal
4712 InvalidOperation = C.InvalidOperation
4713 Context = C.Context
4714 localcontext = C.localcontext
4715
4716 with localcontext(Context()):
4717 self.assertRaises(InvalidOperation, Decimal,
4718 "1e9999999999999999999")
4719
4720 def test_c_context_repr(self):
4721 # This test is _decimal-only because flags are not printed
4722 # in the same order.
4723 DefaultContext = C.DefaultContext
4724 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004725
4726 c = DefaultContext.copy()
4727
4728 c.prec = 425000000
4729 c.Emax = 425000000
4730 c.Emin = -425000000
4731 c.rounding = ROUND_HALF_DOWN
4732 c.capitals = 0
4733 c.clamp = 1
4734 for sig in OrderedSignals[C]:
4735 c.flags[sig] = True
4736 c.traps[sig] = True
4737 c.flags[FloatOperation] = True
4738 c.traps[FloatOperation] = True
4739
4740 s = c.__repr__()
4741 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4742 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4743 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4744 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4745 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4746 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4747 self.assertEqual(s, t)
4748
4749 def test_c_context_errors(self):
4750 Context = C.Context
4751 InvalidOperation = C.InvalidOperation
4752 Overflow = C.Overflow
4753 FloatOperation = C.FloatOperation
4754 localcontext = C.localcontext
4755 getcontext = C.getcontext
4756 setcontext = C.setcontext
4757 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4758
4759 c = Context()
4760
4761 # SignalDict: input validation
4762 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4763 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4764 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4765 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4766 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4767 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4768 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4769 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4770
4771 # Test assignment from a signal dict with the correct length but
4772 # one invalid key.
4773 d = c.flags.copy()
4774 del d[FloatOperation]
4775 d["XYZ"] = 91283719
4776 self.assertRaises(KeyError, setattr, c, 'flags', d)
4777 self.assertRaises(KeyError, setattr, c, 'traps', d)
4778
4779 # Input corner cases
4780 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4781 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4782
4783 # prec, Emax, Emin
4784 for attr in ['prec', 'Emax']:
4785 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4786 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4787
4788 # prec, Emax, Emin in context constructor
4789 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4790 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4791 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4792
4793 # Overflow in conversion
4794 self.assertRaises(OverflowError, Context, prec=int_max+1)
4795 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4796 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004797 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4798 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4799
4800 # OverflowError, general ValueError
4801 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4802 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4803 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4804 if sys.platform != 'win32':
4805 self.assertRaises(ValueError, setattr, c, attr, int_max)
4806 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4807
Stefan Krah1919b7e2012-03-21 18:25:23 +01004808 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4809 if C.MAX_PREC == 425000000:
4810 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4811 int_max+1)
4812 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4813 int_max+1)
4814 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4815 -int_max-2)
4816
4817 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4818 if C.MAX_PREC == 425000000:
4819 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4820 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4821 1070000001)
4822 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4823 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4824 1070000001)
4825 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4826 -1070000001)
4827 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4828
4829 # capitals, clamp
4830 for attr in ['capitals', 'clamp']:
4831 self.assertRaises(ValueError, setattr, c, attr, -1)
4832 self.assertRaises(ValueError, setattr, c, attr, 2)
4833 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4834 if HAVE_CONFIG_64:
4835 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4836 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4837
4838 # Invalid local context
4839 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4840 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004841 self.assertRaises(TypeError, exec,
4842 'with localcontext(context=getcontext()): pass',
4843 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004844
4845 # setcontext
4846 saved_context = getcontext()
4847 self.assertRaises(TypeError, setcontext, "xyz")
4848 setcontext(saved_context)
4849
Stefan Krah59a4a932013-01-16 12:58:59 +01004850 def test_rounding_strings_interned(self):
4851
4852 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4853 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4854 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4855 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4856 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4857 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4858 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4859 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4860
Stefan Krah1919b7e2012-03-21 18:25:23 +01004861 @requires_extra_functionality
4862 def test_c_context_errors_extra(self):
4863 Context = C.Context
4864 InvalidOperation = C.InvalidOperation
4865 Overflow = C.Overflow
4866 localcontext = C.localcontext
4867 getcontext = C.getcontext
4868 setcontext = C.setcontext
4869 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4870
4871 c = Context()
4872
4873 # Input corner cases
4874 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4875
4876 # OverflowError, general ValueError
4877 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4878 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4879 if sys.platform != 'win32':
4880 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4881 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4882
4883 # OverflowError, general TypeError
4884 for attr in ('_flags', '_traps'):
4885 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4886 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4887 if sys.platform != 'win32':
4888 self.assertRaises(TypeError, setattr, c, attr, int_max)
4889 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4890
4891 # _allcr
4892 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4893 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4894 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4895 if HAVE_CONFIG_64:
4896 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4897 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4898
4899 # _flags, _traps
4900 for attr in ['_flags', '_traps']:
4901 self.assertRaises(TypeError, setattr, c, attr, 999999)
4902 self.assertRaises(TypeError, setattr, c, attr, 'x')
4903
4904 def test_c_valid_context(self):
4905 # These tests are for code coverage in _decimal.
4906 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004907 Clamped = C.Clamped
4908 Underflow = C.Underflow
4909 Inexact = C.Inexact
4910 Rounded = C.Rounded
4911 Subnormal = C.Subnormal
4912
4913 c = DefaultContext.copy()
4914
4915 # Exercise all getters and setters
4916 c.prec = 34
4917 c.rounding = ROUND_HALF_UP
4918 c.Emax = 3000
4919 c.Emin = -3000
4920 c.capitals = 1
4921 c.clamp = 0
4922
4923 self.assertEqual(c.prec, 34)
4924 self.assertEqual(c.rounding, ROUND_HALF_UP)
4925 self.assertEqual(c.Emin, -3000)
4926 self.assertEqual(c.Emax, 3000)
4927 self.assertEqual(c.capitals, 1)
4928 self.assertEqual(c.clamp, 0)
4929
4930 self.assertEqual(c.Etiny(), -3033)
4931 self.assertEqual(c.Etop(), 2967)
4932
4933 # Exercise all unsafe setters
4934 if C.MAX_PREC == 425000000:
4935 c._unsafe_setprec(999999999)
4936 c._unsafe_setemax(999999999)
4937 c._unsafe_setemin(-999999999)
4938 self.assertEqual(c.prec, 999999999)
4939 self.assertEqual(c.Emax, 999999999)
4940 self.assertEqual(c.Emin, -999999999)
4941
4942 @requires_extra_functionality
4943 def test_c_valid_context_extra(self):
4944 DefaultContext = C.DefaultContext
4945
4946 c = DefaultContext.copy()
4947 self.assertEqual(c._allcr, 1)
4948 c._allcr = 0
4949 self.assertEqual(c._allcr, 0)
4950
4951 def test_c_round(self):
4952 # Restricted input.
4953 Decimal = C.Decimal
4954 InvalidOperation = C.InvalidOperation
4955 localcontext = C.localcontext
4956 MAX_EMAX = C.MAX_EMAX
4957 MIN_ETINY = C.MIN_ETINY
4958 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4959
4960 with localcontext() as c:
4961 c.traps[InvalidOperation] = True
4962 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4963 -int_max-1)
4964 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4965 int_max)
4966 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4967 int(MAX_EMAX+1))
4968 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4969 -int(MIN_ETINY-1))
4970 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4971 -int_max-2)
4972 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4973 int_max+1)
4974
4975 def test_c_format(self):
4976 # Restricted input
4977 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004978 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4979
4980 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4981 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4982 self.assertRaises(TypeError, Decimal(1).__format__, [])
4983
Stefan Kraheb8c4512013-01-24 15:22:33 +01004984 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4985 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4986 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
4987 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004988
4989 def test_c_integral(self):
4990 Decimal = C.Decimal
4991 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01004992 localcontext = C.localcontext
4993
4994 x = Decimal(10)
4995 self.assertEqual(x.to_integral(), 10)
4996 self.assertRaises(TypeError, x.to_integral, '10')
4997 self.assertRaises(TypeError, x.to_integral, 10, 'x')
4998 self.assertRaises(TypeError, x.to_integral, 10)
4999
5000 self.assertEqual(x.to_integral_value(), 10)
5001 self.assertRaises(TypeError, x.to_integral_value, '10')
5002 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5003 self.assertRaises(TypeError, x.to_integral_value, 10)
5004
5005 self.assertEqual(x.to_integral_exact(), 10)
5006 self.assertRaises(TypeError, x.to_integral_exact, '10')
5007 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5008 self.assertRaises(TypeError, x.to_integral_exact, 10)
5009
5010 with localcontext() as c:
5011 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5012 self.assertEqual(x, Decimal('100000000000000000000000000'))
5013
5014 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5015 self.assertEqual(x, Decimal('100000000000000000000000000'))
5016
5017 c.traps[Inexact] = True
5018 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5019
5020 def test_c_funcs(self):
5021 # Invalid arguments
5022 Decimal = C.Decimal
5023 InvalidOperation = C.InvalidOperation
5024 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005025 getcontext = C.getcontext
5026 localcontext = C.localcontext
5027
5028 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5029
5030 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5031 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5032 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5033
Raymond Hettinger771ed762009-01-03 19:20:32 +00005034 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005035 TypeError,
5036 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005037 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005038 self.assertRaises(
5039 TypeError,
5040 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5041 )
5042 self.assertRaises(
5043 TypeError,
5044 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5045 )
5046 self.assertRaises(
5047 TypeError,
5048 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5049 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005050
Stefan Krah1919b7e2012-03-21 18:25:23 +01005051 with localcontext() as c:
5052 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005053
Stefan Krah1919b7e2012-03-21 18:25:23 +01005054 # Invalid arguments
5055 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5056 self.assertRaises(TypeError, c.canonical, 200)
5057 self.assertRaises(TypeError, c.is_canonical, 200)
5058 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5059 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005060
Stefan Krah1919b7e2012-03-21 18:25:23 +01005061 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5062 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005063
Stefan Krah1919b7e2012-03-21 18:25:23 +01005064 c.traps[DivisionByZero] = True
5065 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5066 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5067 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005068
Stefan Krah1919b7e2012-03-21 18:25:23 +01005069 c.clear_flags()
5070 c.traps[InvalidOperation] = True
5071 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5072 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5073 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005074
Stefan Krah1919b7e2012-03-21 18:25:23 +01005075 c.traps[InvalidOperation] = True
5076 c.prec = 2
5077 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005078
Stefan Krah040e3112012-12-15 22:33:33 +01005079 def test_va_args_exceptions(self):
5080 Decimal = C.Decimal
5081 Context = C.Context
5082
5083 x = Decimal("10001111111")
5084
5085 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5086 'logb', 'logical_invert', 'next_minus', 'next_plus',
5087 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5088 func = getattr(x, attr)
5089 self.assertRaises(TypeError, func, context="x")
5090 self.assertRaises(TypeError, func, "x", context=None)
5091
5092 for attr in ['compare', 'compare_signal', 'logical_and',
5093 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5094 'remainder_near', 'rotate', 'scaleb', 'shift']:
5095 func = getattr(x, attr)
5096 self.assertRaises(TypeError, func, context="x")
5097 self.assertRaises(TypeError, func, "x", context=None)
5098
5099 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5100 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5101 self.assertRaises(TypeError, x.to_integral, [], [])
5102
5103 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5104 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5105 self.assertRaises(TypeError, x.to_integral_value, [], [])
5106
5107 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5108 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5109 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5110
5111 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5112 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5113
5114 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5115 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5116 self.assertRaises(TypeError, x.quantize, 1, [], [])
5117
5118 c = Context()
5119 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5120 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5121 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5122
Stefan Krah1919b7e2012-03-21 18:25:23 +01005123 @requires_extra_functionality
5124 def test_c_context_templates(self):
5125 self.assertEqual(
5126 C.BasicContext._traps,
5127 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5128 C.DecUnderflow|C.DecClamped
5129 )
5130 self.assertEqual(
5131 C.DefaultContext._traps,
5132 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5133 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005134
Stefan Krah1919b7e2012-03-21 18:25:23 +01005135 @requires_extra_functionality
5136 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005137
Stefan Krah1919b7e2012-03-21 18:25:23 +01005138 # SignalDict coverage
5139 Context = C.Context
5140 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005141
Stefan Krah1919b7e2012-03-21 18:25:23 +01005142 InvalidOperation = C.InvalidOperation
5143 DivisionByZero = C.DivisionByZero
5144 Overflow = C.Overflow
5145 Subnormal = C.Subnormal
5146 Underflow = C.Underflow
5147 Rounded = C.Rounded
5148 Inexact = C.Inexact
5149 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005150
Stefan Krah1919b7e2012-03-21 18:25:23 +01005151 DecClamped = C.DecClamped
5152 DecInvalidOperation = C.DecInvalidOperation
5153 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005154
Stefan Krah1919b7e2012-03-21 18:25:23 +01005155 def assertIsExclusivelySet(signal, signal_dict):
5156 for sig in signal_dict:
5157 if sig == signal:
5158 self.assertTrue(signal_dict[sig])
5159 else:
5160 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005161
Stefan Krah1919b7e2012-03-21 18:25:23 +01005162 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005163
Stefan Krah1919b7e2012-03-21 18:25:23 +01005164 # Signal dict methods
5165 self.assertTrue(Overflow in c.traps)
5166 c.clear_traps()
5167 for k in c.traps.keys():
5168 c.traps[k] = True
5169 for v in c.traps.values():
5170 self.assertTrue(v)
5171 c.clear_traps()
5172 for k, v in c.traps.items():
5173 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005174
Stefan Krah1919b7e2012-03-21 18:25:23 +01005175 self.assertFalse(c.flags.get(Overflow))
5176 self.assertIs(c.flags.get("x"), None)
5177 self.assertEqual(c.flags.get("x", "y"), "y")
5178 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005179
Stefan Krah1919b7e2012-03-21 18:25:23 +01005180 self.assertEqual(len(c.flags), len(c.traps))
5181 s = sys.getsizeof(c.flags)
5182 s = sys.getsizeof(c.traps)
5183 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005184
Stefan Krah1919b7e2012-03-21 18:25:23 +01005185 # Set flags/traps.
5186 c.clear_flags()
5187 c._flags = DecClamped
5188 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005189
Stefan Krah1919b7e2012-03-21 18:25:23 +01005190 c.clear_traps()
5191 c._traps = DecInvalidOperation
5192 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005193
Stefan Krah1919b7e2012-03-21 18:25:23 +01005194 # Set flags/traps from dictionary.
5195 c.clear_flags()
5196 d = c.flags.copy()
5197 d[DivisionByZero] = True
5198 c.flags = d
5199 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005200
Stefan Krah1919b7e2012-03-21 18:25:23 +01005201 c.clear_traps()
5202 d = c.traps.copy()
5203 d[Underflow] = True
5204 c.traps = d
5205 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005206
Stefan Krah1919b7e2012-03-21 18:25:23 +01005207 # Random constructors
5208 IntSignals = {
5209 Clamped: C.DecClamped,
5210 Rounded: C.DecRounded,
5211 Inexact: C.DecInexact,
5212 Subnormal: C.DecSubnormal,
5213 Underflow: C.DecUnderflow,
5214 Overflow: C.DecOverflow,
5215 DivisionByZero: C.DecDivisionByZero,
5216 InvalidOperation: C.DecIEEEInvalidOperation
5217 }
5218 IntCond = [
5219 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5220 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5221 C.DecConversionSyntax,
5222 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005223
Stefan Krah1919b7e2012-03-21 18:25:23 +01005224 lim = len(OrderedSignals[C])
5225 for r in range(lim):
5226 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005227 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005228 flags = random.sample(OrderedSignals[C], r)
5229 traps = random.sample(OrderedSignals[C], t)
5230 prec = random.randrange(1, 10000)
5231 emin = random.randrange(-10000, 0)
5232 emax = random.randrange(0, 10000)
5233 clamp = random.randrange(0, 2)
5234 caps = random.randrange(0, 2)
5235 cr = random.randrange(0, 2)
5236 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5237 capitals=caps, clamp=clamp, flags=list(flags),
5238 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005239
Stefan Krah1919b7e2012-03-21 18:25:23 +01005240 self.assertEqual(c.prec, prec)
5241 self.assertEqual(c.rounding, round)
5242 self.assertEqual(c.Emin, emin)
5243 self.assertEqual(c.Emax, emax)
5244 self.assertEqual(c.capitals, caps)
5245 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005246
Stefan Krah1919b7e2012-03-21 18:25:23 +01005247 f = 0
5248 for x in flags:
5249 f |= IntSignals[x]
5250 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005251
Stefan Krah1919b7e2012-03-21 18:25:23 +01005252 f = 0
5253 for x in traps:
5254 f |= IntSignals[x]
5255 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005256
Stefan Krah1919b7e2012-03-21 18:25:23 +01005257 for cond in IntCond:
5258 c._flags = cond
5259 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5260 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005261
Stefan Krah1919b7e2012-03-21 18:25:23 +01005262 for cond in IntCond:
5263 c._traps = cond
5264 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5265 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005266
Stefan Krah1919b7e2012-03-21 18:25:23 +01005267 def test_invalid_override(self):
5268 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005269
Stefan Krah1919b7e2012-03-21 18:25:23 +01005270 try:
5271 from locale import CHAR_MAX
5272 except ImportError:
5273 return
Mark Dickinson84230a12010-02-18 14:49:50 +00005274
Stefan Krah1919b7e2012-03-21 18:25:23 +01005275 def make_grouping(lst):
5276 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005277
Stefan Krah1919b7e2012-03-21 18:25:23 +01005278 def get_fmt(x, override=None, fmt='n'):
5279 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005280
Stefan Krah1919b7e2012-03-21 18:25:23 +01005281 invalid_grouping = {
5282 'decimal_point' : ',',
5283 'grouping' : make_grouping([255, 255, 0]),
5284 'thousands_sep' : ','
5285 }
5286 invalid_dot = {
5287 'decimal_point' : 'xxxxx',
5288 'grouping' : make_grouping([3, 3, 0]),
5289 'thousands_sep' : ','
5290 }
5291 invalid_sep = {
5292 'decimal_point' : '.',
5293 'grouping' : make_grouping([3, 3, 0]),
5294 'thousands_sep' : 'yyyyy'
5295 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005296
Stefan Krah1919b7e2012-03-21 18:25:23 +01005297 if CHAR_MAX == 127: # negative grouping in override
5298 self.assertRaises(ValueError, get_fmt, 12345,
5299 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005300
Stefan Krah1919b7e2012-03-21 18:25:23 +01005301 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5302 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005303
Stefan Krah0774e9b2012-04-05 15:21:58 +02005304 def test_exact_conversion(self):
5305 Decimal = C.Decimal
5306 localcontext = C.localcontext
5307 InvalidOperation = C.InvalidOperation
5308
5309 with localcontext() as c:
5310
5311 c.traps[InvalidOperation] = True
5312
5313 # Clamped
5314 x = "0e%d" % sys.maxsize
5315 self.assertRaises(InvalidOperation, Decimal, x)
5316
5317 x = "0e%d" % (-sys.maxsize-1)
5318 self.assertRaises(InvalidOperation, Decimal, x)
5319
5320 # Overflow
5321 x = "1e%d" % sys.maxsize
5322 self.assertRaises(InvalidOperation, Decimal, x)
5323
5324 # Underflow
5325 x = "1e%d" % (-sys.maxsize-1)
5326 self.assertRaises(InvalidOperation, Decimal, x)
5327
Stefan Krahff3eca02012-04-05 15:46:19 +02005328 def test_from_tuple(self):
5329 Decimal = C.Decimal
5330 localcontext = C.localcontext
5331 InvalidOperation = C.InvalidOperation
5332 Overflow = C.Overflow
5333 Underflow = C.Underflow
5334
5335 with localcontext() as c:
5336
5337 c.traps[InvalidOperation] = True
5338 c.traps[Overflow] = True
5339 c.traps[Underflow] = True
5340
5341 # SSIZE_MAX
5342 x = (1, (), sys.maxsize)
5343 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5344 self.assertRaises(InvalidOperation, Decimal, x)
5345
5346 x = (1, (0, 1, 2), sys.maxsize)
5347 self.assertRaises(Overflow, c.create_decimal, x)
5348 self.assertRaises(InvalidOperation, Decimal, x)
5349
5350 # SSIZE_MIN
5351 x = (1, (), -sys.maxsize-1)
5352 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5353 self.assertRaises(InvalidOperation, Decimal, x)
5354
5355 x = (1, (0, 1, 2), -sys.maxsize-1)
5356 self.assertRaises(Underflow, c.create_decimal, x)
5357 self.assertRaises(InvalidOperation, Decimal, x)
5358
5359 # OverflowError
5360 x = (1, (), sys.maxsize+1)
5361 self.assertRaises(OverflowError, c.create_decimal, x)
5362 self.assertRaises(OverflowError, Decimal, x)
5363
5364 x = (1, (), -sys.maxsize-2)
5365 self.assertRaises(OverflowError, c.create_decimal, x)
5366 self.assertRaises(OverflowError, Decimal, x)
5367
5368 # Specials
5369 x = (1, (), "N")
5370 self.assertEqual(str(Decimal(x)), '-sNaN')
5371 x = (1, (0,), "N")
5372 self.assertEqual(str(Decimal(x)), '-sNaN')
5373 x = (1, (0, 1), "N")
5374 self.assertEqual(str(Decimal(x)), '-sNaN1')
5375
Stefan Krah891ca9e2013-05-29 19:14:17 +02005376 def test_sizeof(self):
5377 Decimal = C.Decimal
5378 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5379
5380 self.assertGreater(Decimal(0).__sizeof__(), 0)
5381 if HAVE_CONFIG_64:
5382 x = Decimal(10**(19*24)).__sizeof__()
5383 y = Decimal(10**(19*25)).__sizeof__()
5384 self.assertEqual(y, x+8)
5385 else:
5386 x = Decimal(10**(9*24)).__sizeof__()
5387 y = Decimal(10**(9*25)).__sizeof__()
5388 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005389
Stefan Krah1919b7e2012-03-21 18:25:23 +01005390all_tests = [
5391 CExplicitConstructionTest, PyExplicitConstructionTest,
5392 CImplicitConstructionTest, PyImplicitConstructionTest,
5393 CFormatTest, PyFormatTest,
5394 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5395 CThreadingTest, PyThreadingTest,
5396 CUsabilityTest, PyUsabilityTest,
5397 CPythonAPItests, PyPythonAPItests,
5398 CContextAPItests, PyContextAPItests,
5399 CContextWithStatement, PyContextWithStatement,
5400 CContextFlags, PyContextFlags,
5401 CSpecialContexts, PySpecialContexts,
5402 CContextInputValidation, PyContextInputValidation,
5403 CContextSubclassing, PyContextSubclassing,
5404 CCoverage, PyCoverage,
5405 CFunctionality, PyFunctionality,
5406 CWhitebox, PyWhitebox,
5407 CIBMTestCases, PyIBMTestCases,
5408]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005409
Stefan Krah1919b7e2012-03-21 18:25:23 +01005410# Delete C tests if _decimal.so is not present.
5411if not C:
5412 all_tests = all_tests[1::2]
5413else:
5414 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005415
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005416
5417def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005418 """ Execute the tests.
5419
Raymond Hettingered20ad82004-09-04 20:09:13 +00005420 Runs all arithmetic tests if arith is True or if the "decimal" resource
5421 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005422 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005423
Stefan Krah1919b7e2012-03-21 18:25:23 +01005424 init(C)
5425 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005426 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00005427 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005428 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005429
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005430 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005431 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005432 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005433 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005434
5435 # Dynamically build custom test definition for each file in the test
5436 # directory and add the definitions to the DecimalTest class. This
5437 # procedure insures that new files do not get skipped.
5438 for filename in os.listdir(directory):
5439 if '.decTest' not in filename or filename.startswith("."):
5440 continue
5441 head, tail = filename.split('.')
5442 if todo_tests is not None and head not in todo_tests:
5443 continue
5444 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005445 setattr(CIBMTestCases, 'test_' + head, tester)
5446 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005447 del filename, head, tail, tester
5448
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005449
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005450 try:
5451 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005452 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005453 from doctest import IGNORE_EXCEPTION_DETAIL
5454 savedecimal = sys.modules['decimal']
5455 if C:
5456 sys.modules['decimal'] = C
5457 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5458 sys.modules['decimal'] = P
5459 run_doctest(P, verbose)
5460 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005461 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005462 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5463 P.setcontext(ORIGINAL_CONTEXT[P])
5464 if not C:
5465 warnings.warn('C tests skipped: no module named _decimal.',
5466 UserWarning)
5467 if not orig_sys_decimal is sys.modules['decimal']:
5468 raise TestFailed("Internal error: unbalanced number of changes to "
5469 "sys.modules['decimal'].")
5470
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005471
5472if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005473 import optparse
5474 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5475 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5476 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5477 (opt, args) = p.parse_args()
5478
5479 if opt.skip:
5480 test_main(arith=False, verbose=True)
5481 elif args:
5482 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005483 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005484 test_main(arith=True, verbose=True)