blob: 1f37b5372a3e7e2be9e2a92309e22a96dbdd082f [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,
Stefan Krah6b794b82014-05-01 17:42:33 +020036 requires_IEEE_754, requires_docstrings)
Victor Stinnerd6debb22017-03-27 16:05:26 +020037from test.support import (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 Krah5de1f822014-05-01 15:53:42 +020040import inspect
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020041import threading
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000042
Raymond Hettingerfed52962004-07-14 15:41:57 +000043
Stefan Krah1919b7e2012-03-21 18:25:23 +010044C = import_fresh_module('decimal', fresh=['_decimal'])
45P = import_fresh_module('decimal', blocked=['_decimal'])
46orig_sys_decimal = sys.modules['decimal']
47
48# fractions module must import the correct decimal module.
49cfractions = import_fresh_module('fractions', fresh=['fractions'])
50sys.modules['decimal'] = P
51pfractions = import_fresh_module('fractions', fresh=['fractions'])
52sys.modules['decimal'] = C
53fractions = {C:cfractions, P:pfractions}
54sys.modules['decimal'] = orig_sys_decimal
55
56
57# Useful Test Constant
58Signals = {
59 C: tuple(C.getcontext().flags.keys()) if C else None,
60 P: tuple(P.getcontext().flags.keys())
61}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000062# Signals ordered with respect to precedence: when an operation
63# produces multiple signals, signals occurring later in the list
64# should be handled before those occurring earlier in the list.
Stefan Krah1919b7e2012-03-21 18:25:23 +010065OrderedSignals = {
66 C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow,
67 C.Overflow, C.DivisionByZero, C.InvalidOperation,
68 C.FloatOperation] if C else None,
69 P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow,
70 P.Overflow, P.DivisionByZero, P.InvalidOperation,
71 P.FloatOperation]
72}
73def assert_signals(cls, context, attr, expected):
74 d = getattr(context, attr)
75 cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
76
Stefan Krah59a4a932013-01-16 12:58:59 +010077ROUND_UP = P.ROUND_UP
78ROUND_DOWN = P.ROUND_DOWN
79ROUND_CEILING = P.ROUND_CEILING
80ROUND_FLOOR = P.ROUND_FLOOR
81ROUND_HALF_UP = P.ROUND_HALF_UP
82ROUND_HALF_DOWN = P.ROUND_HALF_DOWN
83ROUND_HALF_EVEN = P.ROUND_HALF_EVEN
84ROUND_05UP = P.ROUND_05UP
85
86RoundingModes = [
87 ROUND_UP, ROUND_DOWN, ROUND_CEILING, ROUND_FLOOR,
88 ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
89 ROUND_05UP
90]
Mark Dickinsonc69160e2010-05-04 14:35:33 +000091
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000092# Tests are built around these assumed context defaults.
93# test_main() restores the original context.
Stefan Krah1919b7e2012-03-21 18:25:23 +010094ORIGINAL_CONTEXT = {
95 C: C.getcontext().copy() if C else None,
96 P: P.getcontext().copy()
97}
98def init(m):
99 if not m: return
100 DefaultTestContext = m.Context(
Stefan Krah59a4a932013-01-16 12:58:59 +0100101 prec=9, rounding=ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100102 )
103 m.setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +0000104
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000105TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000106if __name__ == '__main__':
107 file = sys.argv[0]
108else:
109 file = __file__
110testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +0000111directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000112
Raymond Hettinger267b8682005-03-27 10:47:39 +0000113skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000114
115# Make sure it actually raises errors when not expected and caught in flags
116# Slower, since it runs some things several times.
117EXTENDEDERRORTEST = False
118
Stefan Krah1919b7e2012-03-21 18:25:23 +0100119# Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
120EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
121requires_extra_functionality = unittest.skipUnless(
122 EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
123skip_if_extra_functionality = unittest.skipIf(
124 EXTRA_FUNCTIONALITY, "test requires regular build")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000125
126
Stefan Krah1919b7e2012-03-21 18:25:23 +0100127class IBMTestCases(unittest.TestCase):
128 """Class which tests the Decimal class against the IBM test cases."""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000129
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000130 def setUp(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100131 self.context = self.decimal.Context()
132 self.readcontext = self.decimal.Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000133 self.ignore_list = ['#']
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000134
Stefan Krah1919b7e2012-03-21 18:25:23 +0100135 # List of individual .decTest test ids that correspond to tests that
136 # we're skipping for one reason or another.
137 self.skipped_test_ids = set([
138 # Skip implementation-specific scaleb tests.
139 'scbx164',
140 'scbx165',
141
142 # For some operations (currently exp, ln, log10, power), the decNumber
143 # reference implementation imposes additional restrictions on the context
144 # and operands. These restrictions are not part of the specification;
145 # however, the effect of these restrictions does show up in some of the
146 # testcases. We skip testcases that violate these restrictions, since
147 # Decimal behaves differently from decNumber for these testcases so these
148 # testcases would otherwise fail.
149 'expx901',
150 'expx902',
151 'expx903',
152 'expx905',
153 'lnx901',
154 'lnx902',
155 'lnx903',
156 'lnx905',
157 'logx901',
158 'logx902',
159 'logx903',
160 'logx905',
161 'powx1183',
162 'powx1184',
163 'powx4001',
164 'powx4002',
165 'powx4003',
166 'powx4005',
167 'powx4008',
168 'powx4010',
169 'powx4012',
170 'powx4014',
171 ])
172
173 if self.decimal == C:
174 # status has additional Subnormal, Underflow
175 self.skipped_test_ids.add('pwsx803')
176 self.skipped_test_ids.add('pwsx805')
177 # Correct rounding (skipped for decNumber, too)
178 self.skipped_test_ids.add('powx4302')
179 self.skipped_test_ids.add('powx4303')
180 self.skipped_test_ids.add('powx4342')
181 self.skipped_test_ids.add('powx4343')
182 # http://bugs.python.org/issue7049
183 self.skipped_test_ids.add('pwmx325')
184 self.skipped_test_ids.add('pwmx326')
185
186 # Map test directives to setter functions.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000187 self.ChangeDict = {'precision' : self.change_precision,
Stefan Krah1919b7e2012-03-21 18:25:23 +0100188 'rounding' : self.change_rounding_method,
189 'maxexponent' : self.change_max_exponent,
190 'minexponent' : self.change_min_exponent,
191 'clamp' : self.change_clamp}
192
193 # Name adapter to be able to change the Decimal and Context
194 # interface without changing the test files from Cowlishaw.
195 self.NameAdapter = {'and':'logical_and',
196 'apply':'_apply',
197 'class':'number_class',
198 'comparesig':'compare_signal',
199 'comparetotal':'compare_total',
200 'comparetotmag':'compare_total_mag',
201 'copy':'copy_decimal',
202 'copyabs':'copy_abs',
203 'copynegate':'copy_negate',
204 'copysign':'copy_sign',
205 'divideint':'divide_int',
206 'invert':'logical_invert',
207 'iscanonical':'is_canonical',
208 'isfinite':'is_finite',
209 'isinfinite':'is_infinite',
210 'isnan':'is_nan',
211 'isnormal':'is_normal',
212 'isqnan':'is_qnan',
213 'issigned':'is_signed',
214 'issnan':'is_snan',
215 'issubnormal':'is_subnormal',
216 'iszero':'is_zero',
217 'maxmag':'max_mag',
218 'minmag':'min_mag',
219 'nextminus':'next_minus',
220 'nextplus':'next_plus',
221 'nexttoward':'next_toward',
222 'or':'logical_or',
223 'reduce':'normalize',
224 'remaindernear':'remainder_near',
225 'samequantum':'same_quantum',
226 'squareroot':'sqrt',
227 'toeng':'to_eng_string',
228 'tointegral':'to_integral_value',
229 'tointegralx':'to_integral_exact',
230 'tosci':'to_sci_string',
231 'xor':'logical_xor'}
232
233 # Map test-case names to roundings.
Stefan Krah59a4a932013-01-16 12:58:59 +0100234 self.RoundingDict = {'ceiling' : ROUND_CEILING,
235 'down' : ROUND_DOWN,
236 'floor' : ROUND_FLOOR,
237 'half_down' : ROUND_HALF_DOWN,
238 'half_even' : ROUND_HALF_EVEN,
239 'half_up' : ROUND_HALF_UP,
240 'up' : ROUND_UP,
241 '05up' : ROUND_05UP}
Stefan Krah1919b7e2012-03-21 18:25:23 +0100242
243 # Map the test cases' error names to the actual errors.
244 self.ErrorNames = {'clamped' : self.decimal.Clamped,
245 'conversion_syntax' : self.decimal.InvalidOperation,
246 'division_by_zero' : self.decimal.DivisionByZero,
247 'division_impossible' : self.decimal.InvalidOperation,
248 'division_undefined' : self.decimal.InvalidOperation,
249 'inexact' : self.decimal.Inexact,
250 'invalid_context' : self.decimal.InvalidOperation,
251 'invalid_operation' : self.decimal.InvalidOperation,
252 'overflow' : self.decimal.Overflow,
253 'rounded' : self.decimal.Rounded,
254 'subnormal' : self.decimal.Subnormal,
255 'underflow' : self.decimal.Underflow}
256
257 # The following functions return True/False rather than a
258 # Decimal instance.
259 self.LogicalFunctions = ('is_canonical',
260 'is_finite',
261 'is_infinite',
262 'is_nan',
263 'is_normal',
264 'is_qnan',
265 'is_signed',
266 'is_snan',
267 'is_subnormal',
268 'is_zero',
269 'same_quantum')
270
271 def read_unlimited(self, v, context):
272 """Work around the limitations of the 32-bit _decimal version. The
273 guaranteed maximum values for prec, Emax etc. are 425000000,
274 but higher values usually work, except for rare corner cases.
275 In particular, all of the IBM tests pass with maximum values
276 of 1070000000."""
277 if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
278 self.readcontext._unsafe_setprec(1070000000)
279 self.readcontext._unsafe_setemax(1070000000)
280 self.readcontext._unsafe_setemin(-1070000000)
281 return self.readcontext.create_decimal(v)
282 else:
283 return self.decimal.Decimal(v, context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000284
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000285 def eval_file(self, file):
286 global skip_expected
287 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000288 raise unittest.SkipTest
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000289 with open(file) as f:
290 for line in f:
291 line = line.replace('\r\n', '').replace('\n', '')
292 #print line
293 try:
294 t = self.eval_line(line)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100295 except self.decimal.DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200296 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000297 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000298
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000299
300 def eval_line(self, s):
301 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
302 s = (s.split('->')[0] + '->' +
303 s.split('->')[1].split('--')[0]).strip()
304 else:
305 s = s.split('--')[0].strip()
306
307 for ignore in self.ignore_list:
308 if s.find(ignore) >= 0:
309 #print s.split()[0], 'NotImplemented--', ignore
310 return
311 if not s:
312 return
313 elif ':' in s:
314 return self.eval_directive(s)
315 else:
316 return self.eval_equation(s)
317
318 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000319 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000320 if funct == 'rounding':
Stefan Krah1919b7e2012-03-21 18:25:23 +0100321 value = self.RoundingDict[value]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000322 else:
323 try:
324 value = int(value)
325 except ValueError:
326 pass
327
Stefan Krah1919b7e2012-03-21 18:25:23 +0100328 funct = self.ChangeDict.get(funct, (lambda *args: None))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000329 funct(value)
330
331 def eval_equation(self, s):
Raymond Hettingered20ad82004-09-04 20:09:13 +0000332
333 if not TEST_ALL and random.random() < 0.90:
334 return
335
Stefan Krah1919b7e2012-03-21 18:25:23 +0100336 self.context.clear_flags()
337
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000338 try:
339 Sides = s.split('->')
340 L = Sides[0].strip().split()
341 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000342 if DEBUG:
343 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000344 funct = L[1].lower()
345 valstemp = L[2:]
346 L = Sides[1].strip().split()
347 ans = L[0]
348 exceptions = L[1:]
349 except (TypeError, AttributeError, IndexError):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100350 raise self.decimal.InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000351 def FixQuotes(val):
352 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
353 val = val.replace("'", '').replace('"', '')
354 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
355 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000356
Stefan Krah1919b7e2012-03-21 18:25:23 +0100357 if id in self.skipped_test_ids:
Mark Dickinson8a546532009-10-08 16:30:38 +0000358 return
359
Stefan Krah1919b7e2012-03-21 18:25:23 +0100360 fname = self.NameAdapter.get(funct, funct)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000361 if fname == 'rescale':
362 return
363 funct = getattr(self.context, fname)
364 vals = []
365 conglomerate = ''
366 quote = 0
Stefan Krah1919b7e2012-03-21 18:25:23 +0100367 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000368
Stefan Krah1919b7e2012-03-21 18:25:23 +0100369 for exception in Signals[self.decimal]:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000370 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000371 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000372 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000373 for i, val in enumerate(valstemp):
374 if val.count("'") % 2 == 1:
375 quote = 1 - quote
376 if quote:
377 conglomerate = conglomerate + ' ' + val
378 continue
379 else:
380 val = conglomerate + val
381 conglomerate = ''
382 v = FixQuotes(val)
383 if fname in ('to_sci_string', 'to_eng_string'):
384 if EXTENDEDERRORTEST:
385 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000386 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000387 try:
388 funct(self.context.create_decimal(v))
389 except error:
390 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100391 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000392 self.fail("Raised %s in %s when %s disabled" % \
393 (e, s, error))
394 else:
395 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000396 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000397 v = self.context.create_decimal(v)
398 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +0100399 v = self.read_unlimited(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000400 vals.append(v)
401
402 ans = FixQuotes(ans)
403
404 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
405 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000406 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000407 try:
408 funct(*vals)
409 except error:
410 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100411 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000412 self.fail("Raised %s in %s when %s disabled" % \
413 (e, s, error))
414 else:
415 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000416 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000417
418 # as above, but add traps cumulatively, to check precedence
Stefan Krah1919b7e2012-03-21 18:25:23 +0100419 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions]
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000420 for error in ordered_errors:
421 self.context.traps[error] = 1
422 try:
423 funct(*vals)
424 except error:
425 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100426 except Signals[self.decimal] as e:
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000427 self.fail("Raised %s in %s; expected %s" %
428 (type(e), s, error))
429 else:
430 self.fail("Did not raise %s in %s" % (error, s))
431 # reset traps
432 for error in ordered_errors:
433 self.context.traps[error] = 0
434
435
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000436 if DEBUG:
437 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000438 try:
439 result = str(funct(*vals))
Stefan Krah1919b7e2012-03-21 18:25:23 +0100440 if fname in self.LogicalFunctions:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000441 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Stefan Krah1919b7e2012-03-21 18:25:23 +0100442 except Signals[self.decimal] as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000443 self.fail("Raised %s in %s" % (error, s))
444 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000445 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000446 raise
447
448 myexceptions = self.getexceptions()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000449
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000450 myexceptions.sort(key=repr)
451 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000452
453 self.assertEqual(result, ans,
454 'Incorrect answer for ' + s + ' -- got ' + result)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100455
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000456 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000457 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000458
459 def getexceptions(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100460 return [e for e in Signals[self.decimal] if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000461
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000462 def change_precision(self, prec):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100463 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
464 self.context._unsafe_setprec(prec)
465 else:
466 self.context.prec = prec
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000467 def change_rounding_method(self, rounding):
468 self.context.rounding = rounding
469 def change_min_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100470 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
471 self.context._unsafe_setemin(exp)
472 else:
473 self.context.Emin = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000474 def change_max_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100475 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
476 self.context._unsafe_setemax(exp)
477 else:
478 self.context.Emax = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000479 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000480 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000481
Stefan Krah1919b7e2012-03-21 18:25:23 +0100482class CIBMTestCases(IBMTestCases):
483 decimal = C
484class PyIBMTestCases(IBMTestCases):
485 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000486
487# The following classes test the behaviour of Decimal according to PEP 327
488
Stefan Krah1919b7e2012-03-21 18:25:23 +0100489class ExplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000490 '''Unit tests for Explicit Construction cases of Decimal.'''
491
492 def test_explicit_empty(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100493 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000494 self.assertEqual(Decimal(), Decimal("0"))
495
496 def test_explicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100497 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000498 self.assertRaises(TypeError, Decimal, None)
499
500 def test_explicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100501 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000502
503 #positive
504 d = Decimal(45)
505 self.assertEqual(str(d), '45')
506
507 #very large positive
508 d = Decimal(500000123)
509 self.assertEqual(str(d), '500000123')
510
511 #negative
512 d = Decimal(-45)
513 self.assertEqual(str(d), '-45')
514
515 #zero
516 d = Decimal(0)
517 self.assertEqual(str(d), '0')
518
Stefan Krah1919b7e2012-03-21 18:25:23 +0100519 # single word longs
520 for n in range(0, 32):
521 for sign in (-1, 1):
522 for x in range(-5, 5):
523 i = sign * (2**n + x)
524 d = Decimal(i)
525 self.assertEqual(str(d), str(i))
526
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000527 def test_explicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100528 Decimal = self.decimal.Decimal
529 InvalidOperation = self.decimal.InvalidOperation
530 localcontext = self.decimal.localcontext
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000531
532 #empty
533 self.assertEqual(str(Decimal('')), 'NaN')
534
535 #int
536 self.assertEqual(str(Decimal('45')), '45')
537
538 #float
539 self.assertEqual(str(Decimal('45.34')), '45.34')
540
541 #engineer notation
542 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
543
544 #just not a number
545 self.assertEqual(str(Decimal('ugly')), 'NaN')
546
Christian Heimesa62da1d2008-01-12 19:39:10 +0000547 #leading and trailing whitespace permitted
548 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
549 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
Stefan Krah1919b7e2012-03-21 18:25:23 +0100550 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
551
Brett Cannona721aba2016-09-09 14:57:09 -0700552 # underscores
553 self.assertEqual(str(Decimal('1_3.3e4_0')), '1.33E+41')
554 self.assertEqual(str(Decimal('1_0_0_0')), '1000')
555
Stefan Krah1919b7e2012-03-21 18:25:23 +0100556 # unicode whitespace
557 for lead in ["", ' ', '\u00a0', '\u205f']:
558 for trail in ["", ' ', '\u00a0', '\u205f']:
559 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
560 '9.311E+28')
561
562 with localcontext() as c:
563 c.traps[InvalidOperation] = True
564 # Invalid string
565 self.assertRaises(InvalidOperation, Decimal, "xyz")
566 # Two arguments max
567 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
568
569 # space within the numeric part
570 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
571 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
572
573 # unicode whitespace
574 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
575 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
576
577 # embedded NUL
578 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
579
Brett Cannona721aba2016-09-09 14:57:09 -0700580 # underscores don't prevent errors
581 self.assertRaises(InvalidOperation, Decimal, "1_2_\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")
Brett Cannona721aba2016-09-09 14:57:09 -0700777 # no whitespace and underscore stripping is done with this method
778 self.assertRaises(InvalidOperation, nc.create_decimal, " 1234")
779 self.assertRaises(InvalidOperation, nc.create_decimal, "12_34")
Stefan Krah1919b7e2012-03-21 18:25:23 +0100780
781 # too many NaN payload digits
782 nc.prec = 3
783 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
784 self.assertRaises(InvalidOperation, nc.create_decimal,
785 Decimal('NaN12345'))
786
787 nc.traps[InvalidOperation] = False
788 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
789 self.assertTrue(nc.flags[InvalidOperation])
790
791 nc.flags[InvalidOperation] = False
792 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
793 self.assertTrue(nc.flags[InvalidOperation])
794
795 def test_explicit_context_create_from_float(self):
796
797 Decimal = self.decimal.Decimal
798
799 nc = self.decimal.Context()
800 r = nc.create_decimal(0.1)
801 self.assertEqual(type(r), Decimal)
802 self.assertEqual(str(r), '0.1000000000000000055511151231')
803 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
804 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
805 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
806 self.assertEqual(str(nc.create_decimal(float('nan'))),
807 str(nc.create_decimal('NaN')))
808 self.assertEqual(str(nc.create_decimal(float('inf'))),
809 str(nc.create_decimal('Infinity')))
810 self.assertEqual(str(nc.create_decimal(float('-inf'))),
811 str(nc.create_decimal('-Infinity')))
812 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
813 str(nc.create_decimal('-0')))
814 nc.prec = 100
815 for i in range(200):
816 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
817 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
818
Mark Dickinson345adc42009-08-02 10:14:23 +0000819 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100820 Decimal = self.decimal.Decimal
821
Mark Dickinson345adc42009-08-02 10:14:23 +0000822 test_values = {
823 '\uff11': '1',
824 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
825 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
826 }
827 for input, expected in test_values.items():
828 self.assertEqual(str(Decimal(input)), expected)
829
Stefan Krah1919b7e2012-03-21 18:25:23 +0100830class CExplicitConstructionTest(ExplicitConstructionTest):
831 decimal = C
832class PyExplicitConstructionTest(ExplicitConstructionTest):
833 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000834
Stefan Krah1919b7e2012-03-21 18:25:23 +0100835class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000836 '''Unit tests for Implicit Construction cases of Decimal.'''
837
838 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100839 Decimal = self.decimal.Decimal
840 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000841
842 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100843 Decimal = self.decimal.Decimal
844
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000845 #normal
846 self.assertEqual(str(Decimal(5) + 45), '50')
847 #exceeding precision
848 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
849
850 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100851 Decimal = self.decimal.Decimal
852 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000853
854 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100855 Decimal = self.decimal.Decimal
856 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000857
858 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100859 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000860 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
861
Raymond Hettinger267b8682005-03-27 10:47:39 +0000862 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100863 Decimal = self.decimal.Decimal
864
Raymond Hettinger267b8682005-03-27 10:47:39 +0000865 # Allow other classes to be trained to interact with Decimals
866 class E:
867 def __divmod__(self, other):
868 return 'divmod ' + str(other)
869 def __rdivmod__(self, other):
870 return str(other) + ' rdivmod'
871 def __lt__(self, other):
872 return 'lt ' + str(other)
873 def __gt__(self, other):
874 return 'gt ' + str(other)
875 def __le__(self, other):
876 return 'le ' + str(other)
877 def __ge__(self, other):
878 return 'ge ' + str(other)
879 def __eq__(self, other):
880 return 'eq ' + str(other)
881 def __ne__(self, other):
882 return 'ne ' + str(other)
883
884 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
885 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
886 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
887 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
888 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
889 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
890 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
891 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
892
893 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000894 oplist = [
895 ('+', '__add__', '__radd__'),
896 ('-', '__sub__', '__rsub__'),
897 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000898 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000899 ('%', '__mod__', '__rmod__'),
900 ('//', '__floordiv__', '__rfloordiv__'),
901 ('**', '__pow__', '__rpow__')
902 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000903
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000904 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000905 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
906 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
907 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
908 'str' + lop + '10')
909 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
910 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000911
Stefan Krah1919b7e2012-03-21 18:25:23 +0100912class CImplicitConstructionTest(ImplicitConstructionTest):
913 decimal = C
914class PyImplicitConstructionTest(ImplicitConstructionTest):
915 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000916
Stefan Krah1919b7e2012-03-21 18:25:23 +0100917class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000918 '''Unit tests for the format function.'''
919 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100920 Decimal = self.decimal.Decimal
921
Christian Heimesf16baeb2008-02-29 14:57:44 +0000922 # triples giving a format, a Decimal, and the expected result
923 test_values = [
924 ('e', '0E-15', '0e-15'),
925 ('e', '2.3E-15', '2.3e-15'),
926 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
927 ('e', '2.30000E-15', '2.30000e-15'),
928 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
929 ('e', '1.5', '1.5e+0'),
930 ('e', '0.15', '1.5e-1'),
931 ('e', '0.015', '1.5e-2'),
932 ('e', '0.0000000000015', '1.5e-12'),
933 ('e', '15.0', '1.50e+1'),
934 ('e', '-15', '-1.5e+1'),
935 ('e', '0', '0e+0'),
936 ('e', '0E1', '0e+1'),
937 ('e', '0.0', '0e-1'),
938 ('e', '0.00', '0e-2'),
939 ('.6e', '0E-15', '0.000000e-9'),
940 ('.6e', '0', '0.000000e+6'),
941 ('.6e', '9.999999', '9.999999e+0'),
942 ('.6e', '9.9999999', '1.000000e+1'),
943 ('.6e', '-1.23e5', '-1.230000e+5'),
944 ('.6e', '1.23456789e-3', '1.234568e-3'),
945 ('f', '0', '0'),
946 ('f', '0.0', '0.0'),
947 ('f', '0E-2', '0.00'),
948 ('f', '0.00E-8', '0.0000000000'),
949 ('f', '0E1', '0'), # loses exponent information
950 ('f', '3.2E1', '32'),
951 ('f', '3.2E2', '320'),
952 ('f', '3.20E2', '320'),
953 ('f', '3.200E2', '320.0'),
954 ('f', '3.2E-6', '0.0000032'),
955 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
956 ('.6f', '0E1', '0.000000'),
957 ('.6f', '0', '0.000000'),
958 ('.0f', '0', '0'), # no decimal point
959 ('.0f', '0e-2', '0'),
960 ('.0f', '3.14159265', '3'),
961 ('.1f', '3.14159265', '3.1'),
962 ('.4f', '3.14159265', '3.1416'),
963 ('.6f', '3.14159265', '3.141593'),
964 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
965 ('.8f', '3.14159265', '3.14159265'),
966 ('.9f', '3.14159265', '3.141592650'),
967
968 ('g', '0', '0'),
969 ('g', '0.0', '0.0'),
970 ('g', '0E1', '0e+1'),
971 ('G', '0E1', '0E+1'),
972 ('g', '0E-5', '0.00000'),
973 ('g', '0E-6', '0.000000'),
974 ('g', '0E-7', '0e-7'),
975 ('g', '-0E2', '-0e+2'),
976 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100977 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000978 ('.1g', '3.14159265', '3'),
979 ('.2g', '3.14159265', '3.1'),
980 ('.5g', '3.14159265', '3.1416'),
981 ('.7g', '3.14159265', '3.141593'),
982 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
983 ('.9g', '3.14159265', '3.14159265'),
984 ('.10g', '3.14159265', '3.14159265'), # don't pad
985
986 ('%', '0E1', '0%'),
987 ('%', '0E0', '0%'),
988 ('%', '0E-1', '0%'),
989 ('%', '0E-2', '0%'),
990 ('%', '0E-3', '0.0%'),
991 ('%', '0E-4', '0.00%'),
992
993 ('.3%', '0', '0.000%'), # all zeros treated equally
994 ('.3%', '0E10', '0.000%'),
995 ('.3%', '0E-10', '0.000%'),
996 ('.3%', '2.34', '234.000%'),
997 ('.3%', '1.234567', '123.457%'),
998 ('.0%', '1.23', '123%'),
999
1000 ('e', 'NaN', 'NaN'),
1001 ('f', '-NaN123', '-NaN123'),
1002 ('+g', 'NaN456', '+NaN456'),
1003 ('.3e', 'Inf', 'Infinity'),
1004 ('.16f', '-Inf', '-Infinity'),
1005 ('.0g', '-sNaN', '-sNaN'),
1006
1007 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001008
Mark Dickinson79f52032009-03-17 23:12:51 +00001009 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001010 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001011 ('<6', '123', '123 '),
1012 ('>6', '123', ' 123'),
1013 ('^6', '123', ' 123 '),
1014 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001015 ('#<10', 'NaN', 'NaN#######'),
1016 ('#<10', '-4.3', '-4.3######'),
1017 ('#<+10', '0.0130', '+0.0130###'),
1018 ('#< 10', '0.0130', ' 0.0130###'),
1019 ('@>10', '-Inf', '@-Infinity'),
1020 ('#>5', '-Inf', '-Infinity'),
1021 ('?^5', '123', '?123?'),
1022 ('%^6', '123', '%123%%'),
1023 (' ^6', '-45.6', '-45.6 '),
1024 ('/=10', '-45.6', '-/////45.6'),
1025 ('/=+10', '45.6', '+/////45.6'),
1026 ('/= 10', '45.6', ' /////45.6'),
Stefan Krah6edda142013-05-29 15:45:38 +02001027 ('\x00=10', '-inf', '-\x00Infinity'),
1028 ('\x00^16', '-inf', '\x00\x00\x00-Infinity\x00\x00\x00\x00'),
1029 ('\x00>10', '1.2345', '\x00\x00\x00\x001.2345'),
1030 ('\x00<10', '1.2345', '1.2345\x00\x00\x00\x00'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001031
1032 # thousands separator
1033 (',', '1234567', '1,234,567'),
1034 (',', '123456', '123,456'),
1035 (',', '12345', '12,345'),
1036 (',', '1234', '1,234'),
1037 (',', '123', '123'),
1038 (',', '12', '12'),
1039 (',', '1', '1'),
1040 (',', '0', '0'),
1041 (',', '-1234567', '-1,234,567'),
1042 (',', '-123456', '-123,456'),
1043 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001044 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001045 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1046 ('+08,', '123456', '+123,456'), # but not if there's a sign
1047 (' 08,', '123456', ' 123,456'),
1048 ('08,', '-123456', '-123,456'),
1049 ('+09,', '123456', '+0,123,456'),
1050 # ... with fractional part...
1051 ('07,', '1234.56', '1,234.56'),
1052 ('08,', '1234.56', '1,234.56'),
1053 ('09,', '1234.56', '01,234.56'),
1054 ('010,', '1234.56', '001,234.56'),
1055 ('011,', '1234.56', '0,001,234.56'),
1056 ('012,', '1234.56', '0,001,234.56'),
1057 ('08,.1f', '1234.5', '01,234.5'),
1058 # no thousands separators in fraction part
1059 (',', '1.23456789', '1.23456789'),
1060 (',%', '123.456789', '12,345.6789%'),
1061 (',e', '123456', '1.23456e+5'),
1062 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001063
1064 # issue 6850
1065 ('a=-7.0', '0.12345', 'aaaa0.1'),
Stefan Krah298131a2014-08-26 20:46:49 +02001066
1067 # issue 22090
1068 ('<^+15.20%', 'inf', '<<+Infinity%<<<'),
1069 ('\x07>,%', 'sNaN1234567', 'sNaN1234567%'),
1070 ('=10.10%', 'NaN123', ' NaN123%'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001071 ]
1072 for fmt, d, result in test_values:
1073 self.assertEqual(format(Decimal(d), fmt), result)
1074
Stefan Krah1919b7e2012-03-21 18:25:23 +01001075 # bytes format argument
1076 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1077
Mark Dickinson79f52032009-03-17 23:12:51 +00001078 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001079 Decimal = self.decimal.Decimal
1080
Mark Dickinson79f52032009-03-17 23:12:51 +00001081 try:
1082 from locale import CHAR_MAX
1083 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06001084 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson79f52032009-03-17 23:12:51 +00001085
Stefan Krah1919b7e2012-03-21 18:25:23 +01001086 def make_grouping(lst):
1087 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1088
1089 def get_fmt(x, override=None, fmt='n'):
1090 if self.decimal == C:
1091 return Decimal(x).__format__(fmt, override)
1092 else:
1093 return Decimal(x).__format__(fmt, _localeconv=override)
1094
Mark Dickinson79f52032009-03-17 23:12:51 +00001095 # Set up some localeconv-like dictionaries
1096 en_US = {
1097 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001098 'grouping' : make_grouping([3, 3, 0]),
1099 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001100 }
1101
1102 fr_FR = {
1103 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001104 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001105 'thousands_sep' : ''
1106 }
1107
1108 ru_RU = {
1109 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001110 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001111 'thousands_sep' : ' '
1112 }
1113
1114 crazy = {
1115 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001116 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001117 'thousands_sep' : '-'
1118 }
1119
Stefan Krah1919b7e2012-03-21 18:25:23 +01001120 dotsep_wide = {
1121 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1122 'grouping': make_grouping([3, 3, 0]),
1123 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1124 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001125
1126 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1127 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1128 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1129 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1130
1131 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1132 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1133 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1134 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1135
1136 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1137 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1138 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1139 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1140
Mark Dickinson7303b592009-03-18 08:25:36 +00001141 # zero padding
1142 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1143 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1144 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1145 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1146
1147 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1148 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1149 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1150 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1151 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1152 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1153
1154 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1155 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1156 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1157 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1158 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1159 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1160 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1161 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1162
Stefan Krah1919b7e2012-03-21 18:25:23 +01001163 # wide char separator and decimal point
1164 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1165 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001166
Stefan Krah6fb204a2012-09-28 16:18:54 +02001167 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001168 def test_wide_char_separator_decimal_point(self):
1169 # locale with wide char separator and decimal point
1170 Decimal = self.decimal.Decimal
1171
Stefan Krah8a491a82012-09-28 17:17:11 +02001172 decimal_point = locale.localeconv()['decimal_point']
1173 thousands_sep = locale.localeconv()['thousands_sep']
Zachary Ware9fe6d862013-12-08 00:20:35 -06001174 if decimal_point != '\u066b':
Serhiy Storchaka34fd4c22018-11-05 16:20:25 +02001175 self.skipTest('inappropriate decimal point separator '
Zachary Ware0f533ac2013-12-12 10:32:16 -06001176 '({!a} not {!a})'.format(decimal_point, '\u066b'))
Zachary Ware9fe6d862013-12-08 00:20:35 -06001177 if thousands_sep != '\u066c':
Serhiy Storchaka34fd4c22018-11-05 16:20:25 +02001178 self.skipTest('inappropriate thousands separator '
Zachary Ware0f533ac2013-12-12 10:32:16 -06001179 '({!a} not {!a})'.format(thousands_sep, '\u066c'))
Stefan Krah8a491a82012-09-28 17:17:11 +02001180
Stefan Krah1919b7e2012-03-21 18:25:23 +01001181 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1182 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001183
Andrew Nester6d1dece2017-02-14 21:22:55 +03001184 def test_decimal_from_float_argument_type(self):
1185 class A(self.decimal.Decimal):
1186 def __init__(self, a):
1187 self.a_type = type(a)
1188 a = A.from_float(42.5)
1189 self.assertEqual(self.decimal.Decimal, a.a_type)
1190
1191 a = A.from_float(42)
1192 self.assertEqual(self.decimal.Decimal, a.a_type)
1193
Stefan Krah1919b7e2012-03-21 18:25:23 +01001194class CFormatTest(FormatTest):
1195 decimal = C
1196class PyFormatTest(FormatTest):
1197 decimal = P
1198
1199class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001200 '''Unit tests for all arithmetic operators, binary and unary.'''
1201
1202 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001203 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001204
1205 d1 = Decimal('-11.1')
1206 d2 = Decimal('22.2')
1207
1208 #two Decimals
1209 self.assertEqual(d1+d2, Decimal('11.1'))
1210 self.assertEqual(d2+d1, Decimal('11.1'))
1211
1212 #with other type, left
1213 c = d1 + 5
1214 self.assertEqual(c, Decimal('-6.1'))
1215 self.assertEqual(type(c), type(d1))
1216
1217 #with other type, right
1218 c = 5 + d1
1219 self.assertEqual(c, Decimal('-6.1'))
1220 self.assertEqual(type(c), type(d1))
1221
1222 #inline with decimal
1223 d1 += d2
1224 self.assertEqual(d1, Decimal('11.1'))
1225
1226 #inline with other type
1227 d1 += 5
1228 self.assertEqual(d1, Decimal('16.1'))
1229
1230 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001231 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001232
1233 d1 = Decimal('-11.1')
1234 d2 = Decimal('22.2')
1235
1236 #two Decimals
1237 self.assertEqual(d1-d2, Decimal('-33.3'))
1238 self.assertEqual(d2-d1, Decimal('33.3'))
1239
1240 #with other type, left
1241 c = d1 - 5
1242 self.assertEqual(c, Decimal('-16.1'))
1243 self.assertEqual(type(c), type(d1))
1244
1245 #with other type, right
1246 c = 5 - d1
1247 self.assertEqual(c, Decimal('16.1'))
1248 self.assertEqual(type(c), type(d1))
1249
1250 #inline with decimal
1251 d1 -= d2
1252 self.assertEqual(d1, Decimal('-33.3'))
1253
1254 #inline with other type
1255 d1 -= 5
1256 self.assertEqual(d1, Decimal('-38.3'))
1257
1258 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001259 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001260
1261 d1 = Decimal('-5')
1262 d2 = Decimal('3')
1263
1264 #two Decimals
1265 self.assertEqual(d1*d2, Decimal('-15'))
1266 self.assertEqual(d2*d1, Decimal('-15'))
1267
1268 #with other type, left
1269 c = d1 * 5
1270 self.assertEqual(c, Decimal('-25'))
1271 self.assertEqual(type(c), type(d1))
1272
1273 #with other type, right
1274 c = 5 * d1
1275 self.assertEqual(c, Decimal('-25'))
1276 self.assertEqual(type(c), type(d1))
1277
1278 #inline with decimal
1279 d1 *= d2
1280 self.assertEqual(d1, Decimal('-15'))
1281
1282 #inline with other type
1283 d1 *= 5
1284 self.assertEqual(d1, Decimal('-75'))
1285
1286 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001287 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001288
1289 d1 = Decimal('-5')
1290 d2 = Decimal('2')
1291
1292 #two Decimals
1293 self.assertEqual(d1/d2, Decimal('-2.5'))
1294 self.assertEqual(d2/d1, Decimal('-0.4'))
1295
1296 #with other type, left
1297 c = d1 / 4
1298 self.assertEqual(c, Decimal('-1.25'))
1299 self.assertEqual(type(c), type(d1))
1300
1301 #with other type, right
1302 c = 4 / d1
1303 self.assertEqual(c, Decimal('-0.8'))
1304 self.assertEqual(type(c), type(d1))
1305
1306 #inline with decimal
1307 d1 /= d2
1308 self.assertEqual(d1, Decimal('-2.5'))
1309
1310 #inline with other type
1311 d1 /= 4
1312 self.assertEqual(d1, Decimal('-0.625'))
1313
1314 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001315 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001316
1317 d1 = Decimal('5')
1318 d2 = Decimal('2')
1319
1320 #two Decimals
1321 self.assertEqual(d1//d2, Decimal('2'))
1322 self.assertEqual(d2//d1, Decimal('0'))
1323
1324 #with other type, left
1325 c = d1 // 4
1326 self.assertEqual(c, Decimal('1'))
1327 self.assertEqual(type(c), type(d1))
1328
1329 #with other type, right
1330 c = 7 // d1
1331 self.assertEqual(c, Decimal('1'))
1332 self.assertEqual(type(c), type(d1))
1333
1334 #inline with decimal
1335 d1 //= d2
1336 self.assertEqual(d1, Decimal('2'))
1337
1338 #inline with other type
1339 d1 //= 2
1340 self.assertEqual(d1, Decimal('1'))
1341
1342 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001343 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001344
1345 d1 = Decimal('5')
1346 d2 = Decimal('2')
1347
1348 #two Decimals
1349 self.assertEqual(d1**d2, Decimal('25'))
1350 self.assertEqual(d2**d1, Decimal('32'))
1351
1352 #with other type, left
1353 c = d1 ** 4
1354 self.assertEqual(c, Decimal('625'))
1355 self.assertEqual(type(c), type(d1))
1356
1357 #with other type, right
1358 c = 7 ** d1
1359 self.assertEqual(c, Decimal('16807'))
1360 self.assertEqual(type(c), type(d1))
1361
1362 #inline with decimal
1363 d1 **= d2
1364 self.assertEqual(d1, Decimal('25'))
1365
1366 #inline with other type
1367 d1 **= 4
1368 self.assertEqual(d1, Decimal('390625'))
1369
1370 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001371 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001372
1373 d1 = Decimal('5')
1374 d2 = Decimal('2')
1375
1376 #two Decimals
1377 self.assertEqual(d1%d2, Decimal('1'))
1378 self.assertEqual(d2%d1, Decimal('2'))
1379
1380 #with other type, left
1381 c = d1 % 4
1382 self.assertEqual(c, Decimal('1'))
1383 self.assertEqual(type(c), type(d1))
1384
1385 #with other type, right
1386 c = 7 % d1
1387 self.assertEqual(c, Decimal('2'))
1388 self.assertEqual(type(c), type(d1))
1389
1390 #inline with decimal
1391 d1 %= d2
1392 self.assertEqual(d1, Decimal('1'))
1393
1394 #inline with other type
1395 d1 %= 4
1396 self.assertEqual(d1, Decimal('1'))
1397
1398 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001399 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001400
1401 d1 = Decimal('5')
1402 d2 = Decimal('2')
1403
1404 #two Decimals
1405 (p, q) = divmod(d1, d2)
1406 self.assertEqual(p, Decimal('2'))
1407 self.assertEqual(q, Decimal('1'))
1408 self.assertEqual(type(p), type(d1))
1409 self.assertEqual(type(q), type(d1))
1410
1411 #with other type, left
1412 (p, q) = divmod(d1, 4)
1413 self.assertEqual(p, Decimal('1'))
1414 self.assertEqual(q, Decimal('1'))
1415 self.assertEqual(type(p), type(d1))
1416 self.assertEqual(type(q), type(d1))
1417
1418 #with other type, right
1419 (p, q) = divmod(7, d1)
1420 self.assertEqual(p, Decimal('1'))
1421 self.assertEqual(q, Decimal('2'))
1422 self.assertEqual(type(p), type(d1))
1423 self.assertEqual(type(q), type(d1))
1424
1425 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001426 Decimal = self.decimal.Decimal
1427
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001428 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1429 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1430 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1431
Christian Heimes77c02eb2008-02-09 02:18:51 +00001432 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001433 # comparisons involving signaling nans signal InvalidOperation
1434
1435 # order comparisons (<, <=, >, >=) involving only quiet nans
1436 # also signal InvalidOperation
1437
1438 # equality comparisons (==, !=) involving only quiet nans
1439 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001440 Decimal = self.decimal.Decimal
1441 InvalidOperation = self.decimal.InvalidOperation
1442 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001443
Christian Heimes77c02eb2008-02-09 02:18:51 +00001444 n = Decimal('NaN')
1445 s = Decimal('sNaN')
1446 i = Decimal('Inf')
1447 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001448
1449 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1450 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1451 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1452 equality_ops = operator.eq, operator.ne
1453
1454 # results when InvalidOperation is not trapped
1455 for x, y in qnan_pairs + snan_pairs:
1456 for op in order_ops + equality_ops:
1457 got = op(x, y)
1458 expected = True if op is operator.ne else False
1459 self.assertIs(expected, got,
1460 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1461 "got {4!r}".format(
1462 expected, op.__name__, x, y, got))
1463
1464 # repeat the above, but this time trap the InvalidOperation
1465 with localcontext() as ctx:
1466 ctx.traps[InvalidOperation] = 1
1467
1468 for x, y in qnan_pairs:
1469 for op in equality_ops:
1470 got = op(x, y)
1471 expected = True if op is operator.ne else False
1472 self.assertIs(expected, got,
1473 "expected {0!r} for "
1474 "operator.{1}({2!r}, {3!r}); "
1475 "got {4!r}".format(
1476 expected, op.__name__, x, y, got))
1477
1478 for x, y in snan_pairs:
1479 for op in equality_ops:
1480 self.assertRaises(InvalidOperation, operator.eq, x, y)
1481 self.assertRaises(InvalidOperation, operator.ne, x, y)
1482
1483 for x, y in qnan_pairs + snan_pairs:
1484 for op in order_ops:
1485 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001486
Mark Dickinson84230a12010-02-18 14:49:50 +00001487 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001488 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001489
Stefan Krah1919b7e2012-03-21 18:25:23 +01001490 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001491 self.assertEqual(Decimal(1).copy_sign(-2), d)
1492 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1493
Stefan Krah1919b7e2012-03-21 18:25:23 +01001494class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1495 decimal = C
1496class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1497 decimal = P
1498
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001499# The following are two functions used to test threading in the next class
1500
1501def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001502 Decimal = cls.decimal.Decimal
1503 InvalidOperation = cls.decimal.InvalidOperation
1504 DivisionByZero = cls.decimal.DivisionByZero
1505 Overflow = cls.decimal.Overflow
1506 Underflow = cls.decimal.Underflow
1507 Inexact = cls.decimal.Inexact
1508 getcontext = cls.decimal.getcontext
1509 localcontext = cls.decimal.localcontext
1510
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001511 d1 = Decimal(1)
1512 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001513 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001514
Stefan Krah1919b7e2012-03-21 18:25:23 +01001515 cls.finish1.set()
1516 cls.synchro.wait()
1517
1518 test2 = d1/d3
1519 with localcontext() as c2:
1520 cls.assertTrue(c2.flags[Inexact])
1521 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1522 cls.assertTrue(c2.flags[DivisionByZero])
1523 with localcontext() as c3:
1524 cls.assertTrue(c3.flags[Inexact])
1525 cls.assertTrue(c3.flags[DivisionByZero])
1526 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1527 cls.assertTrue(c3.flags[InvalidOperation])
1528 del c3
1529 cls.assertFalse(c2.flags[InvalidOperation])
1530 del c2
1531
1532 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1533 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1534
1535 c1 = getcontext()
1536 cls.assertTrue(c1.flags[Inexact])
1537 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1538 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001539
1540def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001541 Decimal = cls.decimal.Decimal
1542 InvalidOperation = cls.decimal.InvalidOperation
1543 DivisionByZero = cls.decimal.DivisionByZero
1544 Overflow = cls.decimal.Overflow
1545 Underflow = cls.decimal.Underflow
1546 Inexact = cls.decimal.Inexact
1547 getcontext = cls.decimal.getcontext
1548 localcontext = cls.decimal.localcontext
1549
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001550 d1 = Decimal(1)
1551 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001552 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001553
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001554 thiscontext = getcontext()
1555 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001556 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001557
1558 with localcontext() as c2:
1559 cls.assertTrue(c2.flags[Inexact])
1560 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1561 cls.assertTrue(c2.flags[Overflow])
1562 with localcontext(thiscontext) as c3:
1563 cls.assertTrue(c3.flags[Inexact])
1564 cls.assertFalse(c3.flags[Overflow])
1565 c3.traps[Underflow] = True
1566 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1567 cls.assertTrue(c3.flags[Underflow])
1568 del c3
1569 cls.assertFalse(c2.flags[Underflow])
1570 cls.assertFalse(c2.traps[Underflow])
1571 del c2
1572
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001573 cls.synchro.set()
1574 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001575
Stefan Krah1919b7e2012-03-21 18:25:23 +01001576 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001577 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001578
1579 cls.assertFalse(thiscontext.traps[Underflow])
1580 cls.assertTrue(thiscontext.flags[Inexact])
1581 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1582 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001583
Stefan Krah1919b7e2012-03-21 18:25:23 +01001584class ThreadingTest(unittest.TestCase):
1585 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001586
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001587 # Take care executing this test from IDLE, there's an issue in threading
1588 # that hangs IDLE and I couldn't find it
1589
1590 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001591 DefaultContext = self.decimal.DefaultContext
1592
1593 if self.decimal == C and not self.decimal.HAVE_THREADS:
1594 self.skipTest("compiled without threading")
1595 # Test the "threading isolation" of a Context. Also test changing
1596 # the DefaultContext, which acts as a template for the thread-local
1597 # contexts.
1598 save_prec = DefaultContext.prec
1599 save_emax = DefaultContext.Emax
1600 save_emin = DefaultContext.Emin
1601 DefaultContext.prec = 24
1602 DefaultContext.Emax = 425000000
1603 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001604
1605 self.synchro = threading.Event()
1606 self.finish1 = threading.Event()
1607 self.finish2 = threading.Event()
1608
1609 th1 = threading.Thread(target=thfunc1, args=(self,))
1610 th2 = threading.Thread(target=thfunc2, args=(self,))
1611
1612 th1.start()
1613 th2.start()
1614
1615 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001616 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001617
1618 for sig in Signals[self.decimal]:
1619 self.assertFalse(DefaultContext.flags[sig])
1620
Victor Stinner18e95b42017-09-14 08:43:04 -07001621 th1.join()
1622 th2.join()
1623
Stefan Krah1919b7e2012-03-21 18:25:23 +01001624 DefaultContext.prec = save_prec
1625 DefaultContext.Emax = save_emax
1626 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001627
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02001628
Stefan Krah1919b7e2012-03-21 18:25:23 +01001629class CThreadingTest(ThreadingTest):
1630 decimal = C
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02001631
Stefan Krah1919b7e2012-03-21 18:25:23 +01001632class PyThreadingTest(ThreadingTest):
1633 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001634
Stefan Krah1919b7e2012-03-21 18:25:23 +01001635class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001636 '''Unit tests for Usability cases of Decimal.'''
1637
1638 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001639
Stefan Krah1919b7e2012-03-21 18:25:23 +01001640 Decimal = self.decimal.Decimal
1641
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001642 da = Decimal('23.42')
1643 db = Decimal('23.42')
1644 dc = Decimal('45')
1645
1646 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001647 self.assertGreater(dc, da)
1648 self.assertGreaterEqual(dc, da)
1649 self.assertLess(da, dc)
1650 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001651 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001652 self.assertNotEqual(da, dc)
1653 self.assertLessEqual(da, db)
1654 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001655
1656 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001657 self.assertGreater(dc, 23)
1658 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001659 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001660
1661 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001662 self.assertNotEqual(da, 'ugly')
1663 self.assertNotEqual(da, 32.7)
1664 self.assertNotEqual(da, object())
1665 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001666
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001667 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001668 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001669 b = a[:]
1670 random.shuffle(a)
1671 a.sort()
1672 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001673
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001674 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001675 Decimal = self.decimal.Decimal
1676
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001677 da = Decimal('0.25')
1678 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001679 self.assertLess(da, 3.0)
1680 self.assertLessEqual(da, 3.0)
1681 self.assertGreater(db, 0.25)
1682 self.assertGreaterEqual(db, 0.25)
1683 self.assertNotEqual(da, 1.5)
1684 self.assertEqual(da, 0.25)
1685 self.assertGreater(3.0, da)
1686 self.assertGreaterEqual(3.0, da)
1687 self.assertLess(0.25, db)
1688 self.assertLessEqual(0.25, db)
1689 self.assertNotEqual(0.25, db)
1690 self.assertEqual(3.0, db)
1691 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001692
Stefan Krah1919b7e2012-03-21 18:25:23 +01001693 def test_decimal_complex_comparison(self):
1694 Decimal = self.decimal.Decimal
1695
1696 da = Decimal('0.25')
1697 db = Decimal('3.0')
1698 self.assertNotEqual(da, (1.5+0j))
1699 self.assertNotEqual((1.5+0j), da)
1700 self.assertEqual(da, (0.25+0j))
1701 self.assertEqual((0.25+0j), da)
1702 self.assertEqual((3.0+0j), db)
1703 self.assertEqual(db, (3.0+0j))
1704
1705 self.assertNotEqual(db, (3.0+1j))
1706 self.assertNotEqual((3.0+1j), db)
1707
1708 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1709 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1710 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1711 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1712
1713 def test_decimal_fraction_comparison(self):
1714 D = self.decimal.Decimal
1715 F = fractions[self.decimal].Fraction
1716 Context = self.decimal.Context
1717 localcontext = self.decimal.localcontext
1718 InvalidOperation = self.decimal.InvalidOperation
1719
1720
1721 emax = C.MAX_EMAX if C else 999999999
1722 emin = C.MIN_EMIN if C else -999999999
1723 etiny = C.MIN_ETINY if C else -1999999997
1724 c = Context(Emax=emax, Emin=emin)
1725
1726 with localcontext(c):
1727 c.prec = emax
1728 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1729 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1730 self.assertLess(F(0,1), D("1e" + str(etiny)))
1731 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1732 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1733 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1734
1735 self.assertEqual(D("0.1"), F(1,10))
1736 self.assertEqual(F(1,10), D("0.1"))
1737
1738 c.prec = 300
1739 self.assertNotEqual(D(1)/3, F(1,3))
1740 self.assertNotEqual(F(1,3), D(1)/3)
1741
1742 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1743 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1744
1745 self.assertGreater(D('inf'), F(99999999999,123))
1746 self.assertGreater(D('inf'), F(-99999999999,123))
1747 self.assertLess(D('-inf'), F(99999999999,123))
1748 self.assertLess(D('-inf'), F(-99999999999,123))
1749
1750 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1751 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1752 self.assertNotEqual(D('nan'), F(-9,123))
1753 self.assertNotEqual(F(-9,123), D('nan'))
1754
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001755 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001756 Decimal = self.decimal.Decimal
1757
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001758 d = Decimal('43.24')
1759 c = copy.copy(d)
1760 self.assertEqual(id(c), id(d))
1761 dc = copy.deepcopy(d)
1762 self.assertEqual(id(dc), id(d))
1763
1764 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001765
1766 Decimal = self.decimal.Decimal
1767 localcontext = self.decimal.localcontext
1768
Stefan Krahdc817b22010-11-17 11:16:34 +00001769 def hashit(d):
1770 a = hash(d)
1771 b = d.__hash__()
1772 self.assertEqual(a, b)
1773 return a
1774
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001775 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001776 hashit(Decimal(23))
1777 hashit(Decimal('Infinity'))
1778 hashit(Decimal('-Infinity'))
1779 hashit(Decimal('nan123'))
1780 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001781
1782 test_values = [Decimal(sign*(2**m + n))
1783 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001784 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001785 for n in range(-10, 10)
1786 for sign in [-1, 1]]
1787 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001788 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001789 Decimal("-0"), # zeros
1790 Decimal("0.00"),
1791 Decimal("-0.000"),
1792 Decimal("0E10"),
1793 Decimal("-0E12"),
1794 Decimal("10.0"), # negative exponent
1795 Decimal("-23.00000"),
1796 Decimal("1230E100"), # positive exponent
1797 Decimal("-4.5678E50"),
1798 # a value for which hash(n) != hash(n % (2**64-1))
1799 # in Python pre-2.6
1800 Decimal(2**64 + 2**32 - 1),
1801 # selection of values which fail with the old (before
1802 # version 2.6) long.__hash__
1803 Decimal("1.634E100"),
1804 Decimal("90.697E100"),
1805 Decimal("188.83E100"),
1806 Decimal("1652.9E100"),
1807 Decimal("56531E100"),
1808 ])
1809
1810 # check that hash(d) == hash(int(d)) for integral values
1811 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001812 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001813
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001814 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001815 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001816 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001817 self.assertTrue(hashit(Decimal('Inf')))
1818 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001819
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001820 # check that the hashes of a Decimal float match when they
1821 # represent exactly the same values
1822 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1823 '34.0', '2.5', '112390.625', '-0.515625']
1824 for s in test_strings:
1825 f = float(s)
1826 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001827 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001828
Stefan Krah1919b7e2012-03-21 18:25:23 +01001829 with localcontext() as c:
1830 # check that the value of the hash doesn't depend on the
1831 # current context (issue #1757)
1832 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001833
Stefan Krah1919b7e2012-03-21 18:25:23 +01001834 c.prec = 6
1835 h1 = hashit(x)
1836 c.prec = 10
1837 h2 = hashit(x)
1838 c.prec = 16
1839 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001840
Stefan Krah1919b7e2012-03-21 18:25:23 +01001841 self.assertEqual(h1, h2)
1842 self.assertEqual(h1, h3)
1843
1844 c.prec = 10000
1845 x = 1100 ** 1248
1846 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001847
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001848 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001849 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001850
1851 d1 = Decimal('15.32')
1852 d2 = Decimal('28.5')
1853 l1 = 15
1854 l2 = 28
1855
1856 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001857 self.assertIs(min(d1,d2), d1)
1858 self.assertIs(min(d2,d1), d1)
1859 self.assertIs(max(d1,d2), d2)
1860 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001861
Serhiy Storchaka95949422013-08-27 19:40:23 +03001862 #between Decimal and int
Ezio Melotti6607d512010-04-03 14:59:49 +00001863 self.assertIs(min(d1,l2), d1)
1864 self.assertIs(min(l2,d1), d1)
1865 self.assertIs(max(l1,d2), d2)
1866 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001867
1868 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001869 Decimal = self.decimal.Decimal
1870
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001871 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001872 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001873 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001874 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001875
1876 def test_tostring_methods(self):
1877 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001878 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001879
1880 d = Decimal('15.32')
1881 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001882 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001883
1884 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001885 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001886 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001887
1888 d1 = Decimal('66')
1889 d2 = Decimal('15.32')
1890
1891 #int
1892 self.assertEqual(int(d1), 66)
1893 self.assertEqual(int(d2), 15)
1894
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001895 #float
1896 self.assertEqual(float(d1), 66)
1897 self.assertEqual(float(d2), 15.32)
1898
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001899 #floor
1900 test_pairs = [
1901 ('123.00', 123),
1902 ('3.2', 3),
1903 ('3.54', 3),
1904 ('3.899', 3),
1905 ('-2.3', -3),
1906 ('-11.0', -11),
1907 ('0.0', 0),
1908 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001909 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001910 ]
1911 for d, i in test_pairs:
1912 self.assertEqual(math.floor(Decimal(d)), i)
1913 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1914 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1915 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1916 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1917 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1918
1919 #ceiling
1920 test_pairs = [
1921 ('123.00', 123),
1922 ('3.2', 4),
1923 ('3.54', 4),
1924 ('3.899', 4),
1925 ('-2.3', -2),
1926 ('-11.0', -11),
1927 ('0.0', 0),
1928 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001929 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001930 ]
1931 for d, i in test_pairs:
1932 self.assertEqual(math.ceil(Decimal(d)), i)
1933 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1934 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1935 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1936 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1937 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1938
1939 #round, single argument
1940 test_pairs = [
1941 ('123.00', 123),
1942 ('3.2', 3),
1943 ('3.54', 4),
1944 ('3.899', 4),
1945 ('-2.3', -2),
1946 ('-11.0', -11),
1947 ('0.0', 0),
1948 ('-0E3', 0),
1949 ('-3.5', -4),
1950 ('-2.5', -2),
1951 ('-1.5', -2),
1952 ('-0.5', 0),
1953 ('0.5', 0),
1954 ('1.5', 2),
1955 ('2.5', 2),
1956 ('3.5', 4),
1957 ]
1958 for d, i in test_pairs:
1959 self.assertEqual(round(Decimal(d)), i)
1960 self.assertRaises(ValueError, round, Decimal('-NaN'))
1961 self.assertRaises(ValueError, round, Decimal('sNaN'))
1962 self.assertRaises(ValueError, round, Decimal('NaN123'))
1963 self.assertRaises(OverflowError, round, Decimal('Inf'))
1964 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1965
1966 #round, two arguments; this is essentially equivalent
1967 #to quantize, which is already extensively tested
1968 test_triples = [
1969 ('123.456', -4, '0E+4'),
1970 ('123.456', -3, '0E+3'),
1971 ('123.456', -2, '1E+2'),
1972 ('123.456', -1, '1.2E+2'),
1973 ('123.456', 0, '123'),
1974 ('123.456', 1, '123.5'),
1975 ('123.456', 2, '123.46'),
1976 ('123.456', 3, '123.456'),
1977 ('123.456', 4, '123.4560'),
1978 ('123.455', 2, '123.46'),
1979 ('123.445', 2, '123.44'),
1980 ('Inf', 4, 'NaN'),
1981 ('-Inf', -23, 'NaN'),
1982 ('sNaN314', 3, 'NaN314'),
1983 ]
1984 for d, n, r in test_triples:
1985 self.assertEqual(str(round(Decimal(d), n)), r)
1986
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001987 def test_nan_to_float(self):
1988 # Test conversions of decimal NANs to float.
1989 # See http://bugs.python.org/issue15544
1990 Decimal = self.decimal.Decimal
1991 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1992 f = float(Decimal(s))
1993 self.assertTrue(math.isnan(f))
1994 sign = math.copysign(1.0, f)
1995 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1996
1997 def test_snan_to_float(self):
1998 Decimal = self.decimal.Decimal
1999 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
2000 d = Decimal(s)
2001 self.assertRaises(ValueError, float, d)
2002
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002003 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002004 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002005
2006 #with zero
2007 d = Decimal( (0, (0,), 0) )
2008 self.assertEqual(d, eval(repr(d)))
2009
2010 #int
2011 d = Decimal( (1, (4, 5), 0) )
2012 self.assertEqual(d, eval(repr(d)))
2013
2014 #float
2015 d = Decimal( (0, (4, 5, 3, 4), -2) )
2016 self.assertEqual(d, eval(repr(d)))
2017
2018 #weird
2019 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2020 self.assertEqual(d, eval(repr(d)))
2021
2022 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002023 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002024
2025 #with zero
2026 d = Decimal(0)
2027 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
2028
2029 #int
2030 d = Decimal(-45)
2031 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2032
2033 #complicated string
2034 d = Decimal("-4.34913534E-17")
2035 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2036
Stefan Krah76e12172012-09-10 19:34:58 +02002037 # The '0' coefficient is implementation specific to decimal.py.
2038 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002039 d = Decimal("Infinity")
2040 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2041
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002042 #leading zeros in coefficient should be stripped
2043 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2044 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2045 d = Decimal( (1, (0, 0, 0), 37) )
2046 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2047 d = Decimal( (1, (), 37) )
2048 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2049
2050 #leading zeros in NaN diagnostic info should be stripped
2051 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2052 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2053 d = Decimal( (1, (0, 0, 0), 'N') )
2054 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2055 d = Decimal( (1, (), 'n') )
2056 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2057
Stefan Krah76e12172012-09-10 19:34:58 +02002058 # For infinities, decimal.py has always silently accepted any
2059 # coefficient tuple.
2060 d = Decimal( (0, (0,), 'F') )
2061 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2062 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2063 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2064 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2065 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002066
Stefan Krah53f2e0a2015-12-28 23:02:02 +01002067 def test_as_integer_ratio(self):
2068 Decimal = self.decimal.Decimal
2069
2070 # exceptional cases
2071 self.assertRaises(OverflowError,
2072 Decimal.as_integer_ratio, Decimal('inf'))
2073 self.assertRaises(OverflowError,
2074 Decimal.as_integer_ratio, Decimal('-inf'))
2075 self.assertRaises(ValueError,
2076 Decimal.as_integer_ratio, Decimal('-nan'))
2077 self.assertRaises(ValueError,
2078 Decimal.as_integer_ratio, Decimal('snan123'))
2079
2080 for exp in range(-4, 2):
2081 for coeff in range(1000):
2082 for sign in '+', '-':
2083 d = Decimal('%s%dE%d' % (sign, coeff, exp))
2084 pq = d.as_integer_ratio()
2085 p, q = pq
2086
2087 # check return type
2088 self.assertIsInstance(pq, tuple)
2089 self.assertIsInstance(p, int)
2090 self.assertIsInstance(q, int)
2091
2092 # check normalization: q should be positive;
2093 # p should be relatively prime to q.
2094 self.assertGreater(q, 0)
2095 self.assertEqual(math.gcd(p, q), 1)
2096
2097 # check that p/q actually gives the correct value
2098 self.assertEqual(Decimal(p) / Decimal(q), d)
2099
Stefan Krah1919b7e2012-03-21 18:25:23 +01002100 def test_subclassing(self):
2101 # Different behaviours when subclassing Decimal
2102 Decimal = self.decimal.Decimal
2103
2104 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002105 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002106
2107 d1 = MyDecimal(1)
2108 d2 = MyDecimal(2)
2109 d = d1 + d2
2110 self.assertIs(type(d), Decimal)
2111
2112 d = d1.max(d2)
2113 self.assertIs(type(d), Decimal)
2114
2115 d = copy.copy(d1)
2116 self.assertIs(type(d), MyDecimal)
2117 self.assertEqual(d, d1)
2118
2119 d = copy.deepcopy(d1)
2120 self.assertIs(type(d), MyDecimal)
2121 self.assertEqual(d, d1)
2122
Stefan Krah0f82b762012-11-08 11:17:29 +01002123 # Decimal(Decimal)
2124 d = Decimal('1.0')
2125 x = Decimal(d)
2126 self.assertIs(type(x), Decimal)
2127 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002128
Stefan Krah0f82b762012-11-08 11:17:29 +01002129 # MyDecimal(Decimal)
2130 m = MyDecimal(d)
2131 self.assertIs(type(m), MyDecimal)
2132 self.assertEqual(m, d)
2133 self.assertIs(m.y, None)
2134
2135 # Decimal(MyDecimal)
2136 x = Decimal(m)
2137 self.assertIs(type(x), Decimal)
2138 self.assertEqual(x, d)
2139
2140 # MyDecimal(MyDecimal)
2141 m.y = 9
2142 x = MyDecimal(m)
2143 self.assertIs(type(x), MyDecimal)
2144 self.assertEqual(x, d)
2145 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002146
Stefan Krah1919b7e2012-03-21 18:25:23 +01002147 def test_implicit_context(self):
2148 Decimal = self.decimal.Decimal
2149 getcontext = self.decimal.getcontext
2150
2151 # Check results when context given implicitly. (Issue 2478)
2152 c = getcontext()
2153 self.assertEqual(str(Decimal(0).sqrt()),
2154 str(c.sqrt(Decimal(0))))
2155
Stefan Krah040e3112012-12-15 22:33:33 +01002156 def test_none_args(self):
2157 Decimal = self.decimal.Decimal
2158 Context = self.decimal.Context
2159 localcontext = self.decimal.localcontext
2160 InvalidOperation = self.decimal.InvalidOperation
2161 DivisionByZero = self.decimal.DivisionByZero
2162 Overflow = self.decimal.Overflow
2163 Underflow = self.decimal.Underflow
2164 Subnormal = self.decimal.Subnormal
2165 Inexact = self.decimal.Inexact
2166 Rounded = self.decimal.Rounded
2167 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002168
2169 with localcontext(Context()) as c:
2170 c.prec = 7
2171 c.Emax = 999
2172 c.Emin = -999
2173
2174 x = Decimal("111")
2175 y = Decimal("1e9999")
2176 z = Decimal("1e-9999")
2177
2178 ##### Unary functions
2179 c.clear_flags()
2180 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2181 self.assertTrue(c.flags[Inexact])
2182 self.assertTrue(c.flags[Rounded])
2183 c.clear_flags()
2184 self.assertRaises(Overflow, y.exp, context=None)
2185 self.assertTrue(c.flags[Overflow])
2186
2187 self.assertIs(z.is_normal(context=None), False)
2188 self.assertIs(z.is_subnormal(context=None), True)
2189
2190 c.clear_flags()
2191 self.assertEqual(str(x.ln(context=None)), '4.709530')
2192 self.assertTrue(c.flags[Inexact])
2193 self.assertTrue(c.flags[Rounded])
2194 c.clear_flags()
2195 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2196 self.assertTrue(c.flags[InvalidOperation])
2197
2198 c.clear_flags()
2199 self.assertEqual(str(x.log10(context=None)), '2.045323')
2200 self.assertTrue(c.flags[Inexact])
2201 self.assertTrue(c.flags[Rounded])
2202 c.clear_flags()
2203 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2204 self.assertTrue(c.flags[InvalidOperation])
2205
2206 c.clear_flags()
2207 self.assertEqual(str(x.logb(context=None)), '2')
2208 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2209 self.assertTrue(c.flags[DivisionByZero])
2210
2211 c.clear_flags()
2212 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2213 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2214 self.assertTrue(c.flags[InvalidOperation])
2215
2216 c.clear_flags()
2217 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2218 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2219 self.assertTrue(c.flags[InvalidOperation])
2220
2221 c.clear_flags()
2222 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2223 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2224 self.assertTrue(c.flags[InvalidOperation])
2225
2226 c.clear_flags()
2227 self.assertEqual(str(z.normalize(context=None)), '0')
2228 self.assertRaises(Overflow, y.normalize, context=None)
2229 self.assertTrue(c.flags[Overflow])
2230
2231 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2232
2233 c.clear_flags()
2234 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2235 self.assertTrue(c.flags[Clamped])
2236 self.assertTrue(c.flags[Inexact])
2237 self.assertTrue(c.flags[Rounded])
2238 self.assertTrue(c.flags[Subnormal])
2239 self.assertTrue(c.flags[Underflow])
2240 c.clear_flags()
2241 self.assertRaises(Overflow, y.sqrt, context=None)
2242 self.assertTrue(c.flags[Overflow])
2243
2244 c.capitals = 0
2245 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2246 c.capitals = 1
2247
2248
2249 ##### Binary functions
2250 c.clear_flags()
2251 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2252 self.assertEqual(ans, 'NaN1287828')
2253 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2254 self.assertTrue(c.flags[InvalidOperation])
2255
2256 c.clear_flags()
2257 ans = str(x.compare_signal(8224, context=None))
2258 self.assertEqual(ans, '-1')
2259 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2260 self.assertTrue(c.flags[InvalidOperation])
2261
2262 c.clear_flags()
2263 ans = str(x.logical_and(101, context=None))
2264 self.assertEqual(ans, '101')
2265 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2266 self.assertTrue(c.flags[InvalidOperation])
2267
2268 c.clear_flags()
2269 ans = str(x.logical_or(101, context=None))
2270 self.assertEqual(ans, '111')
2271 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2272 self.assertTrue(c.flags[InvalidOperation])
2273
2274 c.clear_flags()
2275 ans = str(x.logical_xor(101, context=None))
2276 self.assertEqual(ans, '10')
2277 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2278 self.assertTrue(c.flags[InvalidOperation])
2279
2280 c.clear_flags()
2281 ans = str(x.max(101, context=None))
2282 self.assertEqual(ans, '111')
2283 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2284 self.assertTrue(c.flags[InvalidOperation])
2285
2286 c.clear_flags()
2287 ans = str(x.max_mag(101, context=None))
2288 self.assertEqual(ans, '111')
2289 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2290 self.assertTrue(c.flags[InvalidOperation])
2291
2292 c.clear_flags()
2293 ans = str(x.min(101, context=None))
2294 self.assertEqual(ans, '101')
2295 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2296 self.assertTrue(c.flags[InvalidOperation])
2297
2298 c.clear_flags()
2299 ans = str(x.min_mag(101, context=None))
2300 self.assertEqual(ans, '101')
2301 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2302 self.assertTrue(c.flags[InvalidOperation])
2303
2304 c.clear_flags()
2305 ans = str(x.remainder_near(101, context=None))
2306 self.assertEqual(ans, '10')
2307 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2308 self.assertTrue(c.flags[InvalidOperation])
2309
2310 c.clear_flags()
2311 ans = str(x.rotate(2, context=None))
2312 self.assertEqual(ans, '11100')
2313 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2314 self.assertTrue(c.flags[InvalidOperation])
2315
2316 c.clear_flags()
2317 ans = str(x.scaleb(7, context=None))
2318 self.assertEqual(ans, '1.11E+9')
2319 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2320 self.assertTrue(c.flags[InvalidOperation])
2321
2322 c.clear_flags()
2323 ans = str(x.shift(2, context=None))
2324 self.assertEqual(ans, '11100')
2325 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2326 self.assertTrue(c.flags[InvalidOperation])
2327
2328
2329 ##### Ternary functions
2330 c.clear_flags()
2331 ans = str(x.fma(2, 3, context=None))
2332 self.assertEqual(ans, '225')
2333 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2334 self.assertTrue(c.flags[Overflow])
2335
2336
2337 ##### Special cases
2338 c.rounding = ROUND_HALF_EVEN
2339 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2340 self.assertEqual(ans, '2')
2341 c.rounding = ROUND_DOWN
2342 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2343 self.assertEqual(ans, '1')
2344 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2345 self.assertEqual(ans, '2')
2346 c.clear_flags()
2347 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2348 self.assertTrue(c.flags[InvalidOperation])
2349
2350 c.rounding = ROUND_HALF_EVEN
2351 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2352 self.assertEqual(ans, '2')
2353 c.rounding = ROUND_DOWN
2354 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2355 self.assertEqual(ans, '1')
2356 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2357 self.assertEqual(ans, '2')
2358 c.clear_flags()
2359 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2360 self.assertTrue(c.flags[InvalidOperation])
2361
2362 c.rounding = ROUND_HALF_EVEN
2363 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2364 self.assertEqual(ans, '2')
2365 c.rounding = ROUND_DOWN
2366 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2367 self.assertEqual(ans, '1')
2368 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2369 self.assertEqual(ans, '2')
2370 c.clear_flags()
2371 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2372 self.assertTrue(c.flags[InvalidOperation])
2373
2374 c.rounding = ROUND_UP
2375 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2376 self.assertEqual(ans, '1.501')
2377 c.rounding = ROUND_DOWN
2378 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2379 self.assertEqual(ans, '1.500')
2380 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2381 self.assertEqual(ans, '1.501')
2382 c.clear_flags()
2383 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2384 self.assertTrue(c.flags[InvalidOperation])
2385
2386 with localcontext(Context()) as context:
2387 context.prec = 7
2388 context.Emax = 999
2389 context.Emin = -999
2390 with localcontext(ctx=None) as c:
2391 self.assertEqual(c.prec, 7)
2392 self.assertEqual(c.Emax, 999)
2393 self.assertEqual(c.Emin, -999)
2394
Stefan Krah1919b7e2012-03-21 18:25:23 +01002395 def test_conversions_from_int(self):
2396 # Check that methods taking a second Decimal argument will
2397 # always accept an integer in place of a Decimal.
2398 Decimal = self.decimal.Decimal
2399
2400 self.assertEqual(Decimal(4).compare(3),
2401 Decimal(4).compare(Decimal(3)))
2402 self.assertEqual(Decimal(4).compare_signal(3),
2403 Decimal(4).compare_signal(Decimal(3)))
2404 self.assertEqual(Decimal(4).compare_total(3),
2405 Decimal(4).compare_total(Decimal(3)))
2406 self.assertEqual(Decimal(4).compare_total_mag(3),
2407 Decimal(4).compare_total_mag(Decimal(3)))
2408 self.assertEqual(Decimal(10101).logical_and(1001),
2409 Decimal(10101).logical_and(Decimal(1001)))
2410 self.assertEqual(Decimal(10101).logical_or(1001),
2411 Decimal(10101).logical_or(Decimal(1001)))
2412 self.assertEqual(Decimal(10101).logical_xor(1001),
2413 Decimal(10101).logical_xor(Decimal(1001)))
2414 self.assertEqual(Decimal(567).max(123),
2415 Decimal(567).max(Decimal(123)))
2416 self.assertEqual(Decimal(567).max_mag(123),
2417 Decimal(567).max_mag(Decimal(123)))
2418 self.assertEqual(Decimal(567).min(123),
2419 Decimal(567).min(Decimal(123)))
2420 self.assertEqual(Decimal(567).min_mag(123),
2421 Decimal(567).min_mag(Decimal(123)))
2422 self.assertEqual(Decimal(567).next_toward(123),
2423 Decimal(567).next_toward(Decimal(123)))
2424 self.assertEqual(Decimal(1234).quantize(100),
2425 Decimal(1234).quantize(Decimal(100)))
2426 self.assertEqual(Decimal(768).remainder_near(1234),
2427 Decimal(768).remainder_near(Decimal(1234)))
2428 self.assertEqual(Decimal(123).rotate(1),
2429 Decimal(123).rotate(Decimal(1)))
2430 self.assertEqual(Decimal(1234).same_quantum(1000),
2431 Decimal(1234).same_quantum(Decimal(1000)))
2432 self.assertEqual(Decimal('9.123').scaleb(-100),
2433 Decimal('9.123').scaleb(Decimal(-100)))
2434 self.assertEqual(Decimal(456).shift(-1),
2435 Decimal(456).shift(Decimal(-1)))
2436
2437 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2438 Decimal(-12).fma(Decimal(45), Decimal(67)))
2439 self.assertEqual(Decimal(-12).fma(45, 67),
2440 Decimal(-12).fma(Decimal(45), Decimal(67)))
2441 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2442 Decimal(-12).fma(Decimal(45), Decimal(67)))
2443
2444class CUsabilityTest(UsabilityTest):
2445 decimal = C
2446class PyUsabilityTest(UsabilityTest):
2447 decimal = P
2448
2449class PythonAPItests(unittest.TestCase):
2450
2451 def test_abc(self):
2452 Decimal = self.decimal.Decimal
2453
2454 self.assertTrue(issubclass(Decimal, numbers.Number))
2455 self.assertFalse(issubclass(Decimal, numbers.Real))
2456 self.assertIsInstance(Decimal(0), numbers.Number)
2457 self.assertNotIsInstance(Decimal(0), numbers.Real)
2458
2459 def test_pickle(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +02002460 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2461 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002462
Serhiy Storchakabad12572014-12-15 14:03:42 +02002463 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002464
Serhiy Storchakabad12572014-12-15 14:03:42 +02002465 # Round trip
2466 sys.modules['decimal'] = self.decimal
2467 d = Decimal('-3.141590000')
2468 p = pickle.dumps(d, proto)
2469 e = pickle.loads(p)
2470 self.assertEqual(d, e)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002471
Serhiy Storchakabad12572014-12-15 14:03:42 +02002472 if C:
2473 # Test interchangeability
2474 x = C.Decimal('-3.123e81723')
2475 y = P.Decimal('-3.123e81723')
Stefan Krah1919b7e2012-03-21 18:25:23 +01002476
Serhiy Storchakabad12572014-12-15 14:03:42 +02002477 sys.modules['decimal'] = C
2478 sx = pickle.dumps(x, proto)
2479 sys.modules['decimal'] = P
2480 r = pickle.loads(sx)
2481 self.assertIsInstance(r, P.Decimal)
2482 self.assertEqual(r, y)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002483
Serhiy Storchakabad12572014-12-15 14:03:42 +02002484 sys.modules['decimal'] = P
2485 sy = pickle.dumps(y, proto)
2486 sys.modules['decimal'] = C
2487 r = pickle.loads(sy)
2488 self.assertIsInstance(r, C.Decimal)
2489 self.assertEqual(r, x)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002490
Serhiy Storchakabad12572014-12-15 14:03:42 +02002491 x = C.Decimal('-3.123e81723').as_tuple()
2492 y = P.Decimal('-3.123e81723').as_tuple()
Stefan Krahf1d4e422014-04-29 18:23:35 +02002493
Serhiy Storchakabad12572014-12-15 14:03:42 +02002494 sys.modules['decimal'] = C
2495 sx = pickle.dumps(x, proto)
2496 sys.modules['decimal'] = P
2497 r = pickle.loads(sx)
2498 self.assertIsInstance(r, P.DecimalTuple)
2499 self.assertEqual(r, y)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002500
Serhiy Storchakabad12572014-12-15 14:03:42 +02002501 sys.modules['decimal'] = P
2502 sy = pickle.dumps(y, proto)
2503 sys.modules['decimal'] = C
2504 r = pickle.loads(sy)
2505 self.assertIsInstance(r, C.DecimalTuple)
2506 self.assertEqual(r, x)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002507
Serhiy Storchakabad12572014-12-15 14:03:42 +02002508 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002509
2510 def test_int(self):
2511 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002512
2513 for x in range(-250, 250):
2514 s = '%0.2f' % (x / 100.0)
2515 # should work the same as for floats
2516 self.assertEqual(int(Decimal(s)), int(float(s)))
2517 # should work the same as to_integral in the ROUND_DOWN mode
2518 d = Decimal(s)
2519 r = d.to_integral(ROUND_DOWN)
2520 self.assertEqual(Decimal(int(d)), r)
2521
2522 self.assertRaises(ValueError, int, Decimal('-nan'))
2523 self.assertRaises(ValueError, int, Decimal('snan'))
2524 self.assertRaises(OverflowError, int, Decimal('inf'))
2525 self.assertRaises(OverflowError, int, Decimal('-inf'))
2526
2527 def test_trunc(self):
2528 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002529
2530 for x in range(-250, 250):
2531 s = '%0.2f' % (x / 100.0)
2532 # should work the same as for floats
2533 self.assertEqual(int(Decimal(s)), int(float(s)))
2534 # should work the same as to_integral in the ROUND_DOWN mode
2535 d = Decimal(s)
2536 r = d.to_integral(ROUND_DOWN)
2537 self.assertEqual(Decimal(math.trunc(d)), r)
2538
2539 def test_from_float(self):
2540
2541 Decimal = self.decimal.Decimal
2542
2543 class MyDecimal(Decimal):
Stefan Krah6817c592016-06-20 12:10:13 +02002544 def __init__(self, _):
2545 self.x = 'y'
Stefan Krah1919b7e2012-03-21 18:25:23 +01002546
2547 self.assertTrue(issubclass(MyDecimal, Decimal))
2548
2549 r = MyDecimal.from_float(0.1)
2550 self.assertEqual(type(r), MyDecimal)
2551 self.assertEqual(str(r),
2552 '0.1000000000000000055511151231257827021181583404541015625')
Stefan Krah6817c592016-06-20 12:10:13 +02002553 self.assertEqual(r.x, 'y')
2554
Stefan Krah1919b7e2012-03-21 18:25:23 +01002555 bigint = 12345678901234567890123456789
2556 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2557 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2558 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2559 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2560 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2561 str(Decimal('NaN')))
2562 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2563 str(Decimal('Infinity')))
2564 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2565 str(Decimal('-Infinity')))
2566 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2567 for i in range(200):
2568 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2569 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2570
2571 def test_create_decimal_from_float(self):
2572 Decimal = self.decimal.Decimal
2573 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002574 Inexact = self.decimal.Inexact
2575
2576 context = Context(prec=5, rounding=ROUND_DOWN)
2577 self.assertEqual(
2578 context.create_decimal_from_float(math.pi),
2579 Decimal('3.1415')
2580 )
2581 context = Context(prec=5, rounding=ROUND_UP)
2582 self.assertEqual(
2583 context.create_decimal_from_float(math.pi),
2584 Decimal('3.1416')
2585 )
2586 context = Context(prec=5, traps=[Inexact])
2587 self.assertRaises(
2588 Inexact,
2589 context.create_decimal_from_float,
2590 math.pi
2591 )
2592 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2593 "Decimal('-0')")
2594 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2595 "Decimal('1')")
2596 self.assertEqual(repr(context.create_decimal_from_float(10)),
2597 "Decimal('10')")
2598
2599 def test_quantize(self):
2600 Decimal = self.decimal.Decimal
2601 Context = self.decimal.Context
2602 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002603
2604 c = Context(Emax=99999, Emin=-99999)
2605 self.assertEqual(
2606 Decimal('7.335').quantize(Decimal('.01')),
2607 Decimal('7.34')
2608 )
2609 self.assertEqual(
2610 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2611 Decimal('7.33')
2612 )
2613 self.assertRaises(
2614 InvalidOperation,
2615 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2616 )
2617
2618 c = Context()
2619 d = Decimal("0.871831e800")
2620 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2621 self.assertEqual(x, Decimal('8.71E+799'))
2622
2623 def test_complex(self):
2624 Decimal = self.decimal.Decimal
2625
2626 x = Decimal("9.8182731e181273")
2627 self.assertEqual(x.real, x)
2628 self.assertEqual(x.imag, 0)
2629 self.assertEqual(x.conjugate(), x)
2630
2631 x = Decimal("1")
2632 self.assertEqual(complex(x), complex(float(1)))
2633
2634 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2635 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2636 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2637 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2638
2639 def test_named_parameters(self):
2640 D = self.decimal.Decimal
2641 Context = self.decimal.Context
2642 localcontext = self.decimal.localcontext
2643 InvalidOperation = self.decimal.InvalidOperation
2644 Overflow = self.decimal.Overflow
2645
2646 xc = Context()
2647 xc.prec = 1
2648 xc.Emax = 1
2649 xc.Emin = -1
2650
2651 with localcontext() as c:
2652 c.clear_flags()
2653
2654 self.assertEqual(D(9, xc), 9)
2655 self.assertEqual(D(9, context=xc), 9)
2656 self.assertEqual(D(context=xc, value=9), 9)
2657 self.assertEqual(D(context=xc), 0)
2658 xc.clear_flags()
2659 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2660 self.assertTrue(xc.flags[InvalidOperation])
2661 self.assertFalse(c.flags[InvalidOperation])
2662
2663 xc.clear_flags()
2664 self.assertEqual(D(2).exp(context=xc), 7)
2665 self.assertRaises(Overflow, D(8).exp, context=xc)
2666 self.assertTrue(xc.flags[Overflow])
2667 self.assertFalse(c.flags[Overflow])
2668
2669 xc.clear_flags()
2670 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2671 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2672 self.assertTrue(xc.flags[InvalidOperation])
2673 self.assertFalse(c.flags[InvalidOperation])
2674
2675 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2676 self.assertEqual(D(-1).next_minus(context=xc), -2)
2677 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2678 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2679 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2680 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2681 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2682 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2683
2684 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2685 xc.clear_flags()
2686 self.assertRaises(InvalidOperation,
2687 D("0").compare_signal, D('nan'), context=xc)
2688 self.assertTrue(xc.flags[InvalidOperation])
2689 self.assertFalse(c.flags[InvalidOperation])
2690 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2691 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2692 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2693 D('-0.3'))
2694 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2695 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2696 D('0.0'))
2697 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2698 xc.clear_flags()
2699 self.assertRaises(InvalidOperation,
2700 D("0.2").quantize, D('1e10'), context=xc)
2701 self.assertTrue(xc.flags[InvalidOperation])
2702 self.assertFalse(c.flags[InvalidOperation])
2703 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2704 D('-0.5'))
2705
2706 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2707 D('7E+1'))
2708
2709 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2710 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2711 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2712 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2713 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2714 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2715 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2716 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2717
2718 self.assertFalse(D("0.01").is_normal(context=xc))
2719 self.assertTrue(D("0.01").is_subnormal(context=xc))
2720
2721 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2722 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2723 self.assertRaises(TypeError, D(1).radix, context=xc)
2724
2725 self.assertEqual(D(-111).logb(context=xc), 2)
2726 self.assertEqual(D(0).logical_invert(context=xc), 1)
2727 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2728 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2729
2730 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2731 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2732 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2733 self.assertEqual(D('23').rotate(1, context=xc), 3)
2734 self.assertEqual(D('23').rotate(1, context=xc), 3)
2735 xc.clear_flags()
2736 self.assertRaises(Overflow,
2737 D('23').scaleb, 1, context=xc)
2738 self.assertTrue(xc.flags[Overflow])
2739 self.assertFalse(c.flags[Overflow])
2740 self.assertEqual(D('23').shift(-1, context=xc), 0)
2741
2742 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2743 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2744
Stefan Krah040e3112012-12-15 22:33:33 +01002745 self.assertEqual(D(1).canonical(), 1)
2746 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2747 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2748 self.assertRaises(TypeError, D(1).canonical, context="x")
2749 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002750
Stefan Krahb6405ef2012-03-23 14:46:48 +01002751 def test_exception_hierarchy(self):
2752
2753 decimal = self.decimal
2754 DecimalException = decimal.DecimalException
2755 InvalidOperation = decimal.InvalidOperation
2756 FloatOperation = decimal.FloatOperation
2757 DivisionByZero = decimal.DivisionByZero
2758 Overflow = decimal.Overflow
2759 Underflow = decimal.Underflow
2760 Subnormal = decimal.Subnormal
2761 Inexact = decimal.Inexact
2762 Rounded = decimal.Rounded
2763 Clamped = decimal.Clamped
2764
2765 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2766
2767 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2768 self.assertTrue(issubclass(FloatOperation, DecimalException))
2769 self.assertTrue(issubclass(FloatOperation, TypeError))
2770 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2771 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2772 self.assertTrue(issubclass(Overflow, Rounded))
2773 self.assertTrue(issubclass(Overflow, Inexact))
2774 self.assertTrue(issubclass(Overflow, DecimalException))
2775 self.assertTrue(issubclass(Underflow, Inexact))
2776 self.assertTrue(issubclass(Underflow, Rounded))
2777 self.assertTrue(issubclass(Underflow, Subnormal))
2778 self.assertTrue(issubclass(Underflow, DecimalException))
2779
2780 self.assertTrue(issubclass(Subnormal, DecimalException))
2781 self.assertTrue(issubclass(Inexact, DecimalException))
2782 self.assertTrue(issubclass(Rounded, DecimalException))
2783 self.assertTrue(issubclass(Clamped, DecimalException))
2784
2785 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2786 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2787 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2788 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2789 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2790
Stefan Krah1919b7e2012-03-21 18:25:23 +01002791class CPythonAPItests(PythonAPItests):
2792 decimal = C
2793class PyPythonAPItests(PythonAPItests):
2794 decimal = P
2795
2796class ContextAPItests(unittest.TestCase):
2797
Stefan Krah9a4ff432012-12-16 21:10:35 +01002798 def test_none_args(self):
2799 Context = self.decimal.Context
2800 InvalidOperation = self.decimal.InvalidOperation
2801 DivisionByZero = self.decimal.DivisionByZero
2802 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002803
2804 c1 = Context()
2805 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2806 capitals=None, clamp=None, flags=None, traps=None)
2807 for c in [c1, c2]:
2808 self.assertEqual(c.prec, 28)
2809 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2810 self.assertEqual(c.Emax, 999999)
2811 self.assertEqual(c.Emin, -999999)
2812 self.assertEqual(c.capitals, 1)
2813 self.assertEqual(c.clamp, 0)
2814 assert_signals(self, c, 'flags', [])
2815 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2816 Overflow])
2817
Stefan Krah59a4a932013-01-16 12:58:59 +01002818 @cpython_only
2819 def test_from_legacy_strings(self):
2820 import _testcapi
2821 c = self.decimal.Context()
2822
2823 for rnd in RoundingModes:
2824 c.rounding = _testcapi.unicode_legacy_string(rnd)
2825 self.assertEqual(c.rounding, rnd)
2826
2827 s = _testcapi.unicode_legacy_string('')
2828 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2829
2830 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2831 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2832
Stefan Krah1919b7e2012-03-21 18:25:23 +01002833 def test_pickle(self):
2834
Serhiy Storchakabad12572014-12-15 14:03:42 +02002835 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2836 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002837
Serhiy Storchakabad12572014-12-15 14:03:42 +02002838 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002839
Serhiy Storchakabad12572014-12-15 14:03:42 +02002840 # Round trip
2841 sys.modules['decimal'] = self.decimal
2842 c = Context()
2843 e = pickle.loads(pickle.dumps(c, proto))
Stefan Krah1919b7e2012-03-21 18:25:23 +01002844
Serhiy Storchakabad12572014-12-15 14:03:42 +02002845 self.assertEqual(c.prec, e.prec)
2846 self.assertEqual(c.Emin, e.Emin)
2847 self.assertEqual(c.Emax, e.Emax)
2848 self.assertEqual(c.rounding, e.rounding)
2849 self.assertEqual(c.capitals, e.capitals)
2850 self.assertEqual(c.clamp, e.clamp)
2851 self.assertEqual(c.flags, e.flags)
2852 self.assertEqual(c.traps, e.traps)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002853
Serhiy Storchakabad12572014-12-15 14:03:42 +02002854 # Test interchangeability
2855 combinations = [(C, P), (P, C)] if C else [(P, P)]
2856 for dumper, loader in combinations:
2857 for ri, _ in enumerate(RoundingModes):
2858 for fi, _ in enumerate(OrderedSignals[dumper]):
2859 for ti, _ in enumerate(OrderedSignals[dumper]):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002860
Serhiy Storchakabad12572014-12-15 14:03:42 +02002861 prec = random.randrange(1, 100)
2862 emin = random.randrange(-100, 0)
2863 emax = random.randrange(1, 100)
2864 caps = random.randrange(2)
2865 clamp = random.randrange(2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002866
Serhiy Storchakabad12572014-12-15 14:03:42 +02002867 # One module dumps
2868 sys.modules['decimal'] = dumper
2869 c = dumper.Context(
2870 prec=prec, Emin=emin, Emax=emax,
2871 rounding=RoundingModes[ri],
2872 capitals=caps, clamp=clamp,
2873 flags=OrderedSignals[dumper][:fi],
2874 traps=OrderedSignals[dumper][:ti]
2875 )
2876 s = pickle.dumps(c, proto)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002877
Serhiy Storchakabad12572014-12-15 14:03:42 +02002878 # The other module loads
2879 sys.modules['decimal'] = loader
2880 d = pickle.loads(s)
2881 self.assertIsInstance(d, loader.Context)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002882
Serhiy Storchakabad12572014-12-15 14:03:42 +02002883 self.assertEqual(d.prec, prec)
2884 self.assertEqual(d.Emin, emin)
2885 self.assertEqual(d.Emax, emax)
2886 self.assertEqual(d.rounding, RoundingModes[ri])
2887 self.assertEqual(d.capitals, caps)
2888 self.assertEqual(d.clamp, clamp)
2889 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2890 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002891
Serhiy Storchakabad12572014-12-15 14:03:42 +02002892 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002893
2894 def test_equality_with_other_types(self):
2895 Decimal = self.decimal.Decimal
2896
2897 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2898 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2899
2900 def test_copy(self):
2901 # All copies should be deep
2902 Decimal = self.decimal.Decimal
2903 Context = self.decimal.Context
2904
2905 c = Context()
2906 d = c.copy()
2907 self.assertNotEqual(id(c), id(d))
2908 self.assertNotEqual(id(c.flags), id(d.flags))
2909 self.assertNotEqual(id(c.traps), id(d.traps))
2910 k1 = set(c.flags.keys())
2911 k2 = set(d.flags.keys())
2912 self.assertEqual(k1, k2)
2913 self.assertEqual(c.flags, d.flags)
2914
2915 def test__clamp(self):
2916 # In Python 3.2, the private attribute `_clamp` was made
2917 # public (issue 8540), with the old `_clamp` becoming a
2918 # property wrapping `clamp`. For the duration of Python 3.2
2919 # only, the attribute should be gettable/settable via both
2920 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2921 # removed.
2922 Context = self.decimal.Context
2923 c = Context()
2924 self.assertRaises(AttributeError, getattr, c, '_clamp')
2925
2926 def test_abs(self):
2927 Decimal = self.decimal.Decimal
2928 Context = self.decimal.Context
2929
2930 c = Context()
2931 d = c.abs(Decimal(-1))
2932 self.assertEqual(c.abs(-1), d)
2933 self.assertRaises(TypeError, c.abs, '-1')
2934
2935 def test_add(self):
2936 Decimal = self.decimal.Decimal
2937 Context = self.decimal.Context
2938
2939 c = Context()
2940 d = c.add(Decimal(1), Decimal(1))
2941 self.assertEqual(c.add(1, 1), d)
2942 self.assertEqual(c.add(Decimal(1), 1), d)
2943 self.assertEqual(c.add(1, Decimal(1)), d)
2944 self.assertRaises(TypeError, c.add, '1', 1)
2945 self.assertRaises(TypeError, c.add, 1, '1')
2946
2947 def test_compare(self):
2948 Decimal = self.decimal.Decimal
2949 Context = self.decimal.Context
2950
2951 c = Context()
2952 d = c.compare(Decimal(1), Decimal(1))
2953 self.assertEqual(c.compare(1, 1), d)
2954 self.assertEqual(c.compare(Decimal(1), 1), d)
2955 self.assertEqual(c.compare(1, Decimal(1)), d)
2956 self.assertRaises(TypeError, c.compare, '1', 1)
2957 self.assertRaises(TypeError, c.compare, 1, '1')
2958
2959 def test_compare_signal(self):
2960 Decimal = self.decimal.Decimal
2961 Context = self.decimal.Context
2962
2963 c = Context()
2964 d = c.compare_signal(Decimal(1), Decimal(1))
2965 self.assertEqual(c.compare_signal(1, 1), d)
2966 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2967 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2968 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2969 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2970
2971 def test_compare_total(self):
2972 Decimal = self.decimal.Decimal
2973 Context = self.decimal.Context
2974
2975 c = Context()
2976 d = c.compare_total(Decimal(1), Decimal(1))
2977 self.assertEqual(c.compare_total(1, 1), d)
2978 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2979 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2980 self.assertRaises(TypeError, c.compare_total, '1', 1)
2981 self.assertRaises(TypeError, c.compare_total, 1, '1')
2982
2983 def test_compare_total_mag(self):
2984 Decimal = self.decimal.Decimal
2985 Context = self.decimal.Context
2986
2987 c = Context()
2988 d = c.compare_total_mag(Decimal(1), Decimal(1))
2989 self.assertEqual(c.compare_total_mag(1, 1), d)
2990 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2991 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2992 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2993 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2994
2995 def test_copy_abs(self):
2996 Decimal = self.decimal.Decimal
2997 Context = self.decimal.Context
2998
2999 c = Context()
3000 d = c.copy_abs(Decimal(-1))
3001 self.assertEqual(c.copy_abs(-1), d)
3002 self.assertRaises(TypeError, c.copy_abs, '-1')
3003
3004 def test_copy_decimal(self):
3005 Decimal = self.decimal.Decimal
3006 Context = self.decimal.Context
3007
3008 c = Context()
3009 d = c.copy_decimal(Decimal(-1))
3010 self.assertEqual(c.copy_decimal(-1), d)
3011 self.assertRaises(TypeError, c.copy_decimal, '-1')
3012
3013 def test_copy_negate(self):
3014 Decimal = self.decimal.Decimal
3015 Context = self.decimal.Context
3016
3017 c = Context()
3018 d = c.copy_negate(Decimal(-1))
3019 self.assertEqual(c.copy_negate(-1), d)
3020 self.assertRaises(TypeError, c.copy_negate, '-1')
3021
3022 def test_copy_sign(self):
3023 Decimal = self.decimal.Decimal
3024 Context = self.decimal.Context
3025
3026 c = Context()
3027 d = c.copy_sign(Decimal(1), Decimal(-2))
3028 self.assertEqual(c.copy_sign(1, -2), d)
3029 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
3030 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
3031 self.assertRaises(TypeError, c.copy_sign, '1', -2)
3032 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
3033
3034 def test_divide(self):
3035 Decimal = self.decimal.Decimal
3036 Context = self.decimal.Context
3037
3038 c = Context()
3039 d = c.divide(Decimal(1), Decimal(2))
3040 self.assertEqual(c.divide(1, 2), d)
3041 self.assertEqual(c.divide(Decimal(1), 2), d)
3042 self.assertEqual(c.divide(1, Decimal(2)), d)
3043 self.assertRaises(TypeError, c.divide, '1', 2)
3044 self.assertRaises(TypeError, c.divide, 1, '2')
3045
3046 def test_divide_int(self):
3047 Decimal = self.decimal.Decimal
3048 Context = self.decimal.Context
3049
3050 c = Context()
3051 d = c.divide_int(Decimal(1), Decimal(2))
3052 self.assertEqual(c.divide_int(1, 2), d)
3053 self.assertEqual(c.divide_int(Decimal(1), 2), d)
3054 self.assertEqual(c.divide_int(1, Decimal(2)), d)
3055 self.assertRaises(TypeError, c.divide_int, '1', 2)
3056 self.assertRaises(TypeError, c.divide_int, 1, '2')
3057
3058 def test_divmod(self):
3059 Decimal = self.decimal.Decimal
3060 Context = self.decimal.Context
3061
3062 c = Context()
3063 d = c.divmod(Decimal(1), Decimal(2))
3064 self.assertEqual(c.divmod(1, 2), d)
3065 self.assertEqual(c.divmod(Decimal(1), 2), d)
3066 self.assertEqual(c.divmod(1, Decimal(2)), d)
3067 self.assertRaises(TypeError, c.divmod, '1', 2)
3068 self.assertRaises(TypeError, c.divmod, 1, '2')
3069
3070 def test_exp(self):
3071 Decimal = self.decimal.Decimal
3072 Context = self.decimal.Context
3073
3074 c = Context()
3075 d = c.exp(Decimal(10))
3076 self.assertEqual(c.exp(10), d)
3077 self.assertRaises(TypeError, c.exp, '10')
3078
3079 def test_fma(self):
3080 Decimal = self.decimal.Decimal
3081 Context = self.decimal.Context
3082
3083 c = Context()
3084 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3085 self.assertEqual(c.fma(2, 3, 4), d)
3086 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3087 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3088 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3089 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3090 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3091 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3092 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3093
3094 # Issue 12079 for Context.fma ...
3095 self.assertRaises(TypeError, c.fma,
3096 Decimal('Infinity'), Decimal(0), "not a decimal")
3097 self.assertRaises(TypeError, c.fma,
3098 Decimal(1), Decimal('snan'), 1.222)
3099 # ... and for Decimal.fma.
3100 self.assertRaises(TypeError, Decimal('Infinity').fma,
3101 Decimal(0), "not a decimal")
3102 self.assertRaises(TypeError, Decimal(1).fma,
3103 Decimal('snan'), 1.222)
3104
3105 def test_is_finite(self):
3106 Decimal = self.decimal.Decimal
3107 Context = self.decimal.Context
3108
3109 c = Context()
3110 d = c.is_finite(Decimal(10))
3111 self.assertEqual(c.is_finite(10), d)
3112 self.assertRaises(TypeError, c.is_finite, '10')
3113
3114 def test_is_infinite(self):
3115 Decimal = self.decimal.Decimal
3116 Context = self.decimal.Context
3117
3118 c = Context()
3119 d = c.is_infinite(Decimal(10))
3120 self.assertEqual(c.is_infinite(10), d)
3121 self.assertRaises(TypeError, c.is_infinite, '10')
3122
3123 def test_is_nan(self):
3124 Decimal = self.decimal.Decimal
3125 Context = self.decimal.Context
3126
3127 c = Context()
3128 d = c.is_nan(Decimal(10))
3129 self.assertEqual(c.is_nan(10), d)
3130 self.assertRaises(TypeError, c.is_nan, '10')
3131
3132 def test_is_normal(self):
3133 Decimal = self.decimal.Decimal
3134 Context = self.decimal.Context
3135
3136 c = Context()
3137 d = c.is_normal(Decimal(10))
3138 self.assertEqual(c.is_normal(10), d)
3139 self.assertRaises(TypeError, c.is_normal, '10')
3140
3141 def test_is_qnan(self):
3142 Decimal = self.decimal.Decimal
3143 Context = self.decimal.Context
3144
3145 c = Context()
3146 d = c.is_qnan(Decimal(10))
3147 self.assertEqual(c.is_qnan(10), d)
3148 self.assertRaises(TypeError, c.is_qnan, '10')
3149
3150 def test_is_signed(self):
3151 Decimal = self.decimal.Decimal
3152 Context = self.decimal.Context
3153
3154 c = Context()
3155 d = c.is_signed(Decimal(10))
3156 self.assertEqual(c.is_signed(10), d)
3157 self.assertRaises(TypeError, c.is_signed, '10')
3158
3159 def test_is_snan(self):
3160 Decimal = self.decimal.Decimal
3161 Context = self.decimal.Context
3162
3163 c = Context()
3164 d = c.is_snan(Decimal(10))
3165 self.assertEqual(c.is_snan(10), d)
3166 self.assertRaises(TypeError, c.is_snan, '10')
3167
3168 def test_is_subnormal(self):
3169 Decimal = self.decimal.Decimal
3170 Context = self.decimal.Context
3171
3172 c = Context()
3173 d = c.is_subnormal(Decimal(10))
3174 self.assertEqual(c.is_subnormal(10), d)
3175 self.assertRaises(TypeError, c.is_subnormal, '10')
3176
3177 def test_is_zero(self):
3178 Decimal = self.decimal.Decimal
3179 Context = self.decimal.Context
3180
3181 c = Context()
3182 d = c.is_zero(Decimal(10))
3183 self.assertEqual(c.is_zero(10), d)
3184 self.assertRaises(TypeError, c.is_zero, '10')
3185
3186 def test_ln(self):
3187 Decimal = self.decimal.Decimal
3188 Context = self.decimal.Context
3189
3190 c = Context()
3191 d = c.ln(Decimal(10))
3192 self.assertEqual(c.ln(10), d)
3193 self.assertRaises(TypeError, c.ln, '10')
3194
3195 def test_log10(self):
3196 Decimal = self.decimal.Decimal
3197 Context = self.decimal.Context
3198
3199 c = Context()
3200 d = c.log10(Decimal(10))
3201 self.assertEqual(c.log10(10), d)
3202 self.assertRaises(TypeError, c.log10, '10')
3203
3204 def test_logb(self):
3205 Decimal = self.decimal.Decimal
3206 Context = self.decimal.Context
3207
3208 c = Context()
3209 d = c.logb(Decimal(10))
3210 self.assertEqual(c.logb(10), d)
3211 self.assertRaises(TypeError, c.logb, '10')
3212
3213 def test_logical_and(self):
3214 Decimal = self.decimal.Decimal
3215 Context = self.decimal.Context
3216
3217 c = Context()
3218 d = c.logical_and(Decimal(1), Decimal(1))
3219 self.assertEqual(c.logical_and(1, 1), d)
3220 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3221 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3222 self.assertRaises(TypeError, c.logical_and, '1', 1)
3223 self.assertRaises(TypeError, c.logical_and, 1, '1')
3224
3225 def test_logical_invert(self):
3226 Decimal = self.decimal.Decimal
3227 Context = self.decimal.Context
3228
3229 c = Context()
3230 d = c.logical_invert(Decimal(1000))
3231 self.assertEqual(c.logical_invert(1000), d)
3232 self.assertRaises(TypeError, c.logical_invert, '1000')
3233
3234 def test_logical_or(self):
3235 Decimal = self.decimal.Decimal
3236 Context = self.decimal.Context
3237
3238 c = Context()
3239 d = c.logical_or(Decimal(1), Decimal(1))
3240 self.assertEqual(c.logical_or(1, 1), d)
3241 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3242 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3243 self.assertRaises(TypeError, c.logical_or, '1', 1)
3244 self.assertRaises(TypeError, c.logical_or, 1, '1')
3245
3246 def test_logical_xor(self):
3247 Decimal = self.decimal.Decimal
3248 Context = self.decimal.Context
3249
3250 c = Context()
3251 d = c.logical_xor(Decimal(1), Decimal(1))
3252 self.assertEqual(c.logical_xor(1, 1), d)
3253 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3254 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3255 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3256 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3257
3258 def test_max(self):
3259 Decimal = self.decimal.Decimal
3260 Context = self.decimal.Context
3261
3262 c = Context()
3263 d = c.max(Decimal(1), Decimal(2))
3264 self.assertEqual(c.max(1, 2), d)
3265 self.assertEqual(c.max(Decimal(1), 2), d)
3266 self.assertEqual(c.max(1, Decimal(2)), d)
3267 self.assertRaises(TypeError, c.max, '1', 2)
3268 self.assertRaises(TypeError, c.max, 1, '2')
3269
3270 def test_max_mag(self):
3271 Decimal = self.decimal.Decimal
3272 Context = self.decimal.Context
3273
3274 c = Context()
3275 d = c.max_mag(Decimal(1), Decimal(2))
3276 self.assertEqual(c.max_mag(1, 2), d)
3277 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3278 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3279 self.assertRaises(TypeError, c.max_mag, '1', 2)
3280 self.assertRaises(TypeError, c.max_mag, 1, '2')
3281
3282 def test_min(self):
3283 Decimal = self.decimal.Decimal
3284 Context = self.decimal.Context
3285
3286 c = Context()
3287 d = c.min(Decimal(1), Decimal(2))
3288 self.assertEqual(c.min(1, 2), d)
3289 self.assertEqual(c.min(Decimal(1), 2), d)
3290 self.assertEqual(c.min(1, Decimal(2)), d)
3291 self.assertRaises(TypeError, c.min, '1', 2)
3292 self.assertRaises(TypeError, c.min, 1, '2')
3293
3294 def test_min_mag(self):
3295 Decimal = self.decimal.Decimal
3296 Context = self.decimal.Context
3297
3298 c = Context()
3299 d = c.min_mag(Decimal(1), Decimal(2))
3300 self.assertEqual(c.min_mag(1, 2), d)
3301 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3302 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3303 self.assertRaises(TypeError, c.min_mag, '1', 2)
3304 self.assertRaises(TypeError, c.min_mag, 1, '2')
3305
3306 def test_minus(self):
3307 Decimal = self.decimal.Decimal
3308 Context = self.decimal.Context
3309
3310 c = Context()
3311 d = c.minus(Decimal(10))
3312 self.assertEqual(c.minus(10), d)
3313 self.assertRaises(TypeError, c.minus, '10')
3314
3315 def test_multiply(self):
3316 Decimal = self.decimal.Decimal
3317 Context = self.decimal.Context
3318
3319 c = Context()
3320 d = c.multiply(Decimal(1), Decimal(2))
3321 self.assertEqual(c.multiply(1, 2), d)
3322 self.assertEqual(c.multiply(Decimal(1), 2), d)
3323 self.assertEqual(c.multiply(1, Decimal(2)), d)
3324 self.assertRaises(TypeError, c.multiply, '1', 2)
3325 self.assertRaises(TypeError, c.multiply, 1, '2')
3326
3327 def test_next_minus(self):
3328 Decimal = self.decimal.Decimal
3329 Context = self.decimal.Context
3330
3331 c = Context()
3332 d = c.next_minus(Decimal(10))
3333 self.assertEqual(c.next_minus(10), d)
3334 self.assertRaises(TypeError, c.next_minus, '10')
3335
3336 def test_next_plus(self):
3337 Decimal = self.decimal.Decimal
3338 Context = self.decimal.Context
3339
3340 c = Context()
3341 d = c.next_plus(Decimal(10))
3342 self.assertEqual(c.next_plus(10), d)
3343 self.assertRaises(TypeError, c.next_plus, '10')
3344
3345 def test_next_toward(self):
3346 Decimal = self.decimal.Decimal
3347 Context = self.decimal.Context
3348
3349 c = Context()
3350 d = c.next_toward(Decimal(1), Decimal(2))
3351 self.assertEqual(c.next_toward(1, 2), d)
3352 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3353 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3354 self.assertRaises(TypeError, c.next_toward, '1', 2)
3355 self.assertRaises(TypeError, c.next_toward, 1, '2')
3356
3357 def test_normalize(self):
3358 Decimal = self.decimal.Decimal
3359 Context = self.decimal.Context
3360
3361 c = Context()
3362 d = c.normalize(Decimal(10))
3363 self.assertEqual(c.normalize(10), d)
3364 self.assertRaises(TypeError, c.normalize, '10')
3365
3366 def test_number_class(self):
3367 Decimal = self.decimal.Decimal
3368 Context = self.decimal.Context
3369
3370 c = Context()
3371 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3372 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3373 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3374
3375 def test_plus(self):
3376 Decimal = self.decimal.Decimal
3377 Context = self.decimal.Context
3378
3379 c = Context()
3380 d = c.plus(Decimal(10))
3381 self.assertEqual(c.plus(10), d)
3382 self.assertRaises(TypeError, c.plus, '10')
3383
3384 def test_power(self):
3385 Decimal = self.decimal.Decimal
3386 Context = self.decimal.Context
3387
3388 c = Context()
3389 d = c.power(Decimal(1), Decimal(4))
3390 self.assertEqual(c.power(1, 4), d)
3391 self.assertEqual(c.power(Decimal(1), 4), d)
3392 self.assertEqual(c.power(1, Decimal(4)), d)
3393 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3394 self.assertRaises(TypeError, c.power, '1', 4)
3395 self.assertRaises(TypeError, c.power, 1, '4')
3396 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3397
3398 def test_quantize(self):
3399 Decimal = self.decimal.Decimal
3400 Context = self.decimal.Context
3401
3402 c = Context()
3403 d = c.quantize(Decimal(1), Decimal(2))
3404 self.assertEqual(c.quantize(1, 2), d)
3405 self.assertEqual(c.quantize(Decimal(1), 2), d)
3406 self.assertEqual(c.quantize(1, Decimal(2)), d)
3407 self.assertRaises(TypeError, c.quantize, '1', 2)
3408 self.assertRaises(TypeError, c.quantize, 1, '2')
3409
3410 def test_remainder(self):
3411 Decimal = self.decimal.Decimal
3412 Context = self.decimal.Context
3413
3414 c = Context()
3415 d = c.remainder(Decimal(1), Decimal(2))
3416 self.assertEqual(c.remainder(1, 2), d)
3417 self.assertEqual(c.remainder(Decimal(1), 2), d)
3418 self.assertEqual(c.remainder(1, Decimal(2)), d)
3419 self.assertRaises(TypeError, c.remainder, '1', 2)
3420 self.assertRaises(TypeError, c.remainder, 1, '2')
3421
3422 def test_remainder_near(self):
3423 Decimal = self.decimal.Decimal
3424 Context = self.decimal.Context
3425
3426 c = Context()
3427 d = c.remainder_near(Decimal(1), Decimal(2))
3428 self.assertEqual(c.remainder_near(1, 2), d)
3429 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3430 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3431 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3432 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3433
3434 def test_rotate(self):
3435 Decimal = self.decimal.Decimal
3436 Context = self.decimal.Context
3437
3438 c = Context()
3439 d = c.rotate(Decimal(1), Decimal(2))
3440 self.assertEqual(c.rotate(1, 2), d)
3441 self.assertEqual(c.rotate(Decimal(1), 2), d)
3442 self.assertEqual(c.rotate(1, Decimal(2)), d)
3443 self.assertRaises(TypeError, c.rotate, '1', 2)
3444 self.assertRaises(TypeError, c.rotate, 1, '2')
3445
3446 def test_sqrt(self):
3447 Decimal = self.decimal.Decimal
3448 Context = self.decimal.Context
3449
3450 c = Context()
3451 d = c.sqrt(Decimal(10))
3452 self.assertEqual(c.sqrt(10), d)
3453 self.assertRaises(TypeError, c.sqrt, '10')
3454
3455 def test_same_quantum(self):
3456 Decimal = self.decimal.Decimal
3457 Context = self.decimal.Context
3458
3459 c = Context()
3460 d = c.same_quantum(Decimal(1), Decimal(2))
3461 self.assertEqual(c.same_quantum(1, 2), d)
3462 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3463 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3464 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3465 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3466
3467 def test_scaleb(self):
3468 Decimal = self.decimal.Decimal
3469 Context = self.decimal.Context
3470
3471 c = Context()
3472 d = c.scaleb(Decimal(1), Decimal(2))
3473 self.assertEqual(c.scaleb(1, 2), d)
3474 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3475 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3476 self.assertRaises(TypeError, c.scaleb, '1', 2)
3477 self.assertRaises(TypeError, c.scaleb, 1, '2')
3478
3479 def test_shift(self):
3480 Decimal = self.decimal.Decimal
3481 Context = self.decimal.Context
3482
3483 c = Context()
3484 d = c.shift(Decimal(1), Decimal(2))
3485 self.assertEqual(c.shift(1, 2), d)
3486 self.assertEqual(c.shift(Decimal(1), 2), d)
3487 self.assertEqual(c.shift(1, Decimal(2)), d)
3488 self.assertRaises(TypeError, c.shift, '1', 2)
3489 self.assertRaises(TypeError, c.shift, 1, '2')
3490
3491 def test_subtract(self):
3492 Decimal = self.decimal.Decimal
3493 Context = self.decimal.Context
3494
3495 c = Context()
3496 d = c.subtract(Decimal(1), Decimal(2))
3497 self.assertEqual(c.subtract(1, 2), d)
3498 self.assertEqual(c.subtract(Decimal(1), 2), d)
3499 self.assertEqual(c.subtract(1, Decimal(2)), d)
3500 self.assertRaises(TypeError, c.subtract, '1', 2)
3501 self.assertRaises(TypeError, c.subtract, 1, '2')
3502
3503 def test_to_eng_string(self):
3504 Decimal = self.decimal.Decimal
3505 Context = self.decimal.Context
3506
3507 c = Context()
3508 d = c.to_eng_string(Decimal(10))
3509 self.assertEqual(c.to_eng_string(10), d)
3510 self.assertRaises(TypeError, c.to_eng_string, '10')
3511
3512 def test_to_sci_string(self):
3513 Decimal = self.decimal.Decimal
3514 Context = self.decimal.Context
3515
3516 c = Context()
3517 d = c.to_sci_string(Decimal(10))
3518 self.assertEqual(c.to_sci_string(10), d)
3519 self.assertRaises(TypeError, c.to_sci_string, '10')
3520
3521 def test_to_integral_exact(self):
3522 Decimal = self.decimal.Decimal
3523 Context = self.decimal.Context
3524
3525 c = Context()
3526 d = c.to_integral_exact(Decimal(10))
3527 self.assertEqual(c.to_integral_exact(10), d)
3528 self.assertRaises(TypeError, c.to_integral_exact, '10')
3529
3530 def test_to_integral_value(self):
3531 Decimal = self.decimal.Decimal
3532 Context = self.decimal.Context
3533
3534 c = Context()
3535 d = c.to_integral_value(Decimal(10))
3536 self.assertEqual(c.to_integral_value(10), d)
3537 self.assertRaises(TypeError, c.to_integral_value, '10')
3538 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3539
3540class CContextAPItests(ContextAPItests):
3541 decimal = C
3542class PyContextAPItests(ContextAPItests):
3543 decimal = P
3544
3545class ContextWithStatement(unittest.TestCase):
3546 # Can't do these as docstrings until Python 2.6
3547 # as doctest can't handle __future__ statements
3548
3549 def test_localcontext(self):
3550 # Use a copy of the current context in the block
3551 getcontext = self.decimal.getcontext
3552 localcontext = self.decimal.localcontext
3553
3554 orig_ctx = getcontext()
3555 with localcontext() as enter_ctx:
3556 set_ctx = getcontext()
3557 final_ctx = getcontext()
3558 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3559 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3560 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3561
3562 def test_localcontextarg(self):
3563 # Use a copy of the supplied context in the block
3564 Context = self.decimal.Context
3565 getcontext = self.decimal.getcontext
3566 localcontext = self.decimal.localcontext
3567
3568 localcontext = self.decimal.localcontext
3569 orig_ctx = getcontext()
3570 new_ctx = Context(prec=42)
3571 with localcontext(new_ctx) as enter_ctx:
3572 set_ctx = getcontext()
3573 final_ctx = getcontext()
3574 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3575 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3576 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3577 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3578
3579 def test_nested_with_statements(self):
3580 # Use a copy of the supplied context in the block
3581 Decimal = self.decimal.Decimal
3582 Context = self.decimal.Context
3583 getcontext = self.decimal.getcontext
3584 localcontext = self.decimal.localcontext
3585 Clamped = self.decimal.Clamped
3586 Overflow = self.decimal.Overflow
3587
3588 orig_ctx = getcontext()
3589 orig_ctx.clear_flags()
3590 new_ctx = Context(Emax=384)
3591 with localcontext() as c1:
3592 self.assertEqual(c1.flags, orig_ctx.flags)
3593 self.assertEqual(c1.traps, orig_ctx.traps)
3594 c1.traps[Clamped] = True
3595 c1.Emin = -383
3596 self.assertNotEqual(orig_ctx.Emin, -383)
3597 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3598 self.assertTrue(c1.flags[Clamped])
3599 with localcontext(new_ctx) as c2:
3600 self.assertEqual(c2.flags, new_ctx.flags)
3601 self.assertEqual(c2.traps, new_ctx.traps)
3602 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3603 self.assertFalse(c2.flags[Clamped])
3604 self.assertTrue(c2.flags[Overflow])
3605 del c2
3606 self.assertFalse(c1.flags[Overflow])
3607 del c1
3608 self.assertNotEqual(orig_ctx.Emin, -383)
3609 self.assertFalse(orig_ctx.flags[Clamped])
3610 self.assertFalse(orig_ctx.flags[Overflow])
3611 self.assertFalse(new_ctx.flags[Clamped])
3612 self.assertFalse(new_ctx.flags[Overflow])
3613
3614 def test_with_statements_gc1(self):
3615 localcontext = self.decimal.localcontext
3616
3617 with localcontext() as c1:
3618 del c1
3619 with localcontext() as c2:
3620 del c2
3621 with localcontext() as c3:
3622 del c3
3623 with localcontext() as c4:
3624 del c4
3625
3626 def test_with_statements_gc2(self):
3627 localcontext = self.decimal.localcontext
3628
3629 with localcontext() as c1:
3630 with localcontext(c1) as c2:
3631 del c1
3632 with localcontext(c2) as c3:
3633 del c2
3634 with localcontext(c3) as c4:
3635 del c3
3636 del c4
3637
3638 def test_with_statements_gc3(self):
3639 Context = self.decimal.Context
3640 localcontext = self.decimal.localcontext
3641 getcontext = self.decimal.getcontext
3642 setcontext = self.decimal.setcontext
3643
3644 with localcontext() as c1:
3645 del c1
3646 n1 = Context(prec=1)
3647 setcontext(n1)
3648 with localcontext(n1) as c2:
3649 del n1
3650 self.assertEqual(c2.prec, 1)
3651 del c2
3652 n2 = Context(prec=2)
3653 setcontext(n2)
3654 del n2
3655 self.assertEqual(getcontext().prec, 2)
3656 n3 = Context(prec=3)
3657 setcontext(n3)
3658 self.assertEqual(getcontext().prec, 3)
3659 with localcontext(n3) as c3:
3660 del n3
3661 self.assertEqual(c3.prec, 3)
3662 del c3
3663 n4 = Context(prec=4)
3664 setcontext(n4)
3665 del n4
3666 self.assertEqual(getcontext().prec, 4)
3667 with localcontext() as c4:
3668 self.assertEqual(c4.prec, 4)
3669 del c4
3670
3671class CContextWithStatement(ContextWithStatement):
3672 decimal = C
3673class PyContextWithStatement(ContextWithStatement):
3674 decimal = P
3675
3676class ContextFlags(unittest.TestCase):
3677
3678 def test_flags_irrelevant(self):
3679 # check that the result (numeric result + flags raised) of an
3680 # arithmetic operation doesn't depend on the current flags
3681 Decimal = self.decimal.Decimal
3682 Context = self.decimal.Context
3683 Inexact = self.decimal.Inexact
3684 Rounded = self.decimal.Rounded
3685 Underflow = self.decimal.Underflow
3686 Clamped = self.decimal.Clamped
3687 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003688
3689 def raise_error(context, flag):
3690 if self.decimal == C:
3691 context.flags[flag] = True
3692 if context.traps[flag]:
3693 raise flag
3694 else:
3695 context._raise_error(flag)
3696
3697 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3698 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3699
3700 # operations that raise various flags, in the form (function, arglist)
3701 operations = [
3702 (context._apply, [Decimal("100E-425000010")]),
3703 (context.sqrt, [Decimal(2)]),
3704 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3705 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3706 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3707 ]
3708
3709 # try various flags individually, then a whole lot at once
3710 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3711 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3712
3713 for fn, args in operations:
3714 # find answer and flags raised using a clean context
3715 context.clear_flags()
3716 ans = fn(*args)
3717 flags = [k for k, v in context.flags.items() if v]
3718
3719 for extra_flags in flagsets:
3720 # set flags, before calling operation
3721 context.clear_flags()
3722 for flag in extra_flags:
3723 raise_error(context, flag)
3724 new_ans = fn(*args)
3725
3726 # flags that we expect to be set after the operation
3727 expected_flags = list(flags)
3728 for flag in extra_flags:
3729 if flag not in expected_flags:
3730 expected_flags.append(flag)
3731 expected_flags.sort(key=id)
3732
3733 # flags we actually got
3734 new_flags = [k for k,v in context.flags.items() if v]
3735 new_flags.sort(key=id)
3736
3737 self.assertEqual(ans, new_ans,
3738 "operation produces different answers depending on flags set: " +
3739 "expected %s, got %s." % (ans, new_ans))
3740 self.assertEqual(new_flags, expected_flags,
3741 "operation raises different flags depending on flags set: " +
3742 "expected %s, got %s" % (expected_flags, new_flags))
3743
3744 def test_flag_comparisons(self):
3745 Context = self.decimal.Context
3746 Inexact = self.decimal.Inexact
3747 Rounded = self.decimal.Rounded
3748
3749 c = Context()
3750
3751 # Valid SignalDict
3752 self.assertNotEqual(c.flags, c.traps)
3753 self.assertNotEqual(c.traps, c.flags)
3754
3755 c.flags = c.traps
3756 self.assertEqual(c.flags, c.traps)
3757 self.assertEqual(c.traps, c.flags)
3758
3759 c.flags[Rounded] = True
3760 c.traps = c.flags
3761 self.assertEqual(c.flags, c.traps)
3762 self.assertEqual(c.traps, c.flags)
3763
3764 d = {}
3765 d.update(c.flags)
3766 self.assertEqual(d, c.flags)
3767 self.assertEqual(c.flags, d)
3768
3769 d[Inexact] = True
3770 self.assertNotEqual(d, c.flags)
3771 self.assertNotEqual(c.flags, d)
3772
3773 # Invalid SignalDict
3774 d = {Inexact:False}
3775 self.assertNotEqual(d, c.flags)
3776 self.assertNotEqual(c.flags, d)
3777
3778 d = ["xyz"]
3779 self.assertNotEqual(d, c.flags)
3780 self.assertNotEqual(c.flags, d)
3781
3782 @requires_IEEE_754
3783 def test_float_operation(self):
3784 Decimal = self.decimal.Decimal
3785 FloatOperation = self.decimal.FloatOperation
3786 localcontext = self.decimal.localcontext
3787
3788 with localcontext() as c:
3789 ##### trap is off by default
3790 self.assertFalse(c.traps[FloatOperation])
3791
3792 # implicit conversion sets the flag
3793 c.clear_flags()
3794 self.assertEqual(Decimal(7.5), 7.5)
3795 self.assertTrue(c.flags[FloatOperation])
3796
3797 c.clear_flags()
3798 self.assertEqual(c.create_decimal(7.5), 7.5)
3799 self.assertTrue(c.flags[FloatOperation])
3800
3801 # explicit conversion does not set the flag
3802 c.clear_flags()
3803 x = Decimal.from_float(7.5)
3804 self.assertFalse(c.flags[FloatOperation])
3805 # comparison sets the flag
3806 self.assertEqual(x, 7.5)
3807 self.assertTrue(c.flags[FloatOperation])
3808
3809 c.clear_flags()
3810 x = c.create_decimal_from_float(7.5)
3811 self.assertFalse(c.flags[FloatOperation])
3812 self.assertEqual(x, 7.5)
3813 self.assertTrue(c.flags[FloatOperation])
3814
3815 ##### set the trap
3816 c.traps[FloatOperation] = True
3817
3818 # implicit conversion raises
3819 c.clear_flags()
3820 self.assertRaises(FloatOperation, Decimal, 7.5)
3821 self.assertTrue(c.flags[FloatOperation])
3822
3823 c.clear_flags()
3824 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3825 self.assertTrue(c.flags[FloatOperation])
3826
3827 # explicit conversion is silent
3828 c.clear_flags()
3829 x = Decimal.from_float(7.5)
3830 self.assertFalse(c.flags[FloatOperation])
3831
3832 c.clear_flags()
3833 x = c.create_decimal_from_float(7.5)
3834 self.assertFalse(c.flags[FloatOperation])
3835
3836 def test_float_comparison(self):
3837 Decimal = self.decimal.Decimal
3838 Context = self.decimal.Context
3839 FloatOperation = self.decimal.FloatOperation
3840 localcontext = self.decimal.localcontext
3841
3842 def assert_attr(a, b, attr, context, signal=None):
3843 context.clear_flags()
3844 f = getattr(a, attr)
3845 if signal == FloatOperation:
3846 self.assertRaises(signal, f, b)
3847 else:
3848 self.assertIs(f(b), True)
3849 self.assertTrue(context.flags[FloatOperation])
3850
3851 small_d = Decimal('0.25')
3852 big_d = Decimal('3.0')
3853 small_f = 0.25
3854 big_f = 3.0
3855
3856 zero_d = Decimal('0.0')
3857 neg_zero_d = Decimal('-0.0')
3858 zero_f = 0.0
3859 neg_zero_f = -0.0
3860
3861 inf_d = Decimal('Infinity')
3862 neg_inf_d = Decimal('-Infinity')
3863 inf_f = float('inf')
3864 neg_inf_f = float('-inf')
3865
3866 def doit(c, signal=None):
3867 # Order
3868 for attr in '__lt__', '__le__':
3869 assert_attr(small_d, big_f, attr, c, signal)
3870
3871 for attr in '__gt__', '__ge__':
3872 assert_attr(big_d, small_f, attr, c, signal)
3873
3874 # Equality
3875 assert_attr(small_d, small_f, '__eq__', c, None)
3876
3877 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3878 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3879
3880 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3881 assert_attr(zero_d, zero_f, '__eq__', c, None)
3882
3883 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3884 assert_attr(inf_d, inf_f, '__eq__', c, None)
3885
3886 # Inequality
3887 assert_attr(small_d, big_f, '__ne__', c, None)
3888
3889 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3890
3891 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3892 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3893
3894 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3895
3896 def test_containers(c, signal=None):
3897 c.clear_flags()
3898 s = set([100.0, Decimal('100.0')])
3899 self.assertEqual(len(s), 1)
3900 self.assertTrue(c.flags[FloatOperation])
3901
3902 c.clear_flags()
3903 if signal:
3904 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3905 else:
3906 s = sorted([10.0, Decimal('10.0')])
3907 self.assertTrue(c.flags[FloatOperation])
3908
3909 c.clear_flags()
3910 b = 10.0 in [Decimal('10.0'), 1.0]
3911 self.assertTrue(c.flags[FloatOperation])
3912
3913 c.clear_flags()
3914 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3915 self.assertTrue(c.flags[FloatOperation])
3916
3917 nc = Context()
3918 with localcontext(nc) as c:
3919 self.assertFalse(c.traps[FloatOperation])
3920 doit(c, signal=None)
3921 test_containers(c, signal=None)
3922
3923 c.traps[FloatOperation] = True
3924 doit(c, signal=FloatOperation)
3925 test_containers(c, signal=FloatOperation)
3926
3927 def test_float_operation_default(self):
3928 Decimal = self.decimal.Decimal
3929 Context = self.decimal.Context
3930 Inexact = self.decimal.Inexact
3931 FloatOperation= self.decimal.FloatOperation
3932
3933 context = Context()
3934 self.assertFalse(context.flags[FloatOperation])
3935 self.assertFalse(context.traps[FloatOperation])
3936
3937 context.clear_traps()
3938 context.traps[Inexact] = True
3939 context.traps[FloatOperation] = True
3940 self.assertTrue(context.traps[FloatOperation])
3941 self.assertTrue(context.traps[Inexact])
3942
3943class CContextFlags(ContextFlags):
3944 decimal = C
3945class PyContextFlags(ContextFlags):
3946 decimal = P
3947
3948class SpecialContexts(unittest.TestCase):
3949 """Test the context templates."""
3950
3951 def test_context_templates(self):
3952 BasicContext = self.decimal.BasicContext
3953 ExtendedContext = self.decimal.ExtendedContext
3954 getcontext = self.decimal.getcontext
3955 setcontext = self.decimal.setcontext
3956 InvalidOperation = self.decimal.InvalidOperation
3957 DivisionByZero = self.decimal.DivisionByZero
3958 Overflow = self.decimal.Overflow
3959 Underflow = self.decimal.Underflow
3960 Clamped = self.decimal.Clamped
3961
3962 assert_signals(self, BasicContext, 'traps',
3963 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3964 )
3965
3966 savecontext = getcontext().copy()
3967 basic_context_prec = BasicContext.prec
3968 extended_context_prec = ExtendedContext.prec
3969
3970 ex = None
3971 try:
3972 BasicContext.prec = ExtendedContext.prec = 441
3973 for template in BasicContext, ExtendedContext:
3974 setcontext(template)
3975 c = getcontext()
3976 self.assertIsNot(c, template)
3977 self.assertEqual(c.prec, 441)
3978 except Exception as e:
3979 ex = e.__class__
3980 finally:
3981 BasicContext.prec = basic_context_prec
3982 ExtendedContext.prec = extended_context_prec
3983 setcontext(savecontext)
3984 if ex:
3985 raise ex
3986
3987 def test_default_context(self):
3988 DefaultContext = self.decimal.DefaultContext
3989 BasicContext = self.decimal.BasicContext
3990 ExtendedContext = self.decimal.ExtendedContext
3991 getcontext = self.decimal.getcontext
3992 setcontext = self.decimal.setcontext
3993 InvalidOperation = self.decimal.InvalidOperation
3994 DivisionByZero = self.decimal.DivisionByZero
3995 Overflow = self.decimal.Overflow
3996
3997 self.assertEqual(BasicContext.prec, 9)
3998 self.assertEqual(ExtendedContext.prec, 9)
3999
4000 assert_signals(self, DefaultContext, 'traps',
4001 [InvalidOperation, DivisionByZero, Overflow]
4002 )
4003
4004 savecontext = getcontext().copy()
4005 default_context_prec = DefaultContext.prec
4006
4007 ex = None
4008 try:
4009 c = getcontext()
4010 saveprec = c.prec
4011
4012 DefaultContext.prec = 961
4013 c = getcontext()
4014 self.assertEqual(c.prec, saveprec)
4015
4016 setcontext(DefaultContext)
4017 c = getcontext()
4018 self.assertIsNot(c, DefaultContext)
4019 self.assertEqual(c.prec, 961)
4020 except Exception as e:
4021 ex = e.__class__
4022 finally:
4023 DefaultContext.prec = default_context_prec
4024 setcontext(savecontext)
4025 if ex:
4026 raise ex
4027
4028class CSpecialContexts(SpecialContexts):
4029 decimal = C
4030class PySpecialContexts(SpecialContexts):
4031 decimal = P
4032
4033class ContextInputValidation(unittest.TestCase):
4034
4035 def test_invalid_context(self):
4036 Context = self.decimal.Context
4037 DefaultContext = self.decimal.DefaultContext
4038
4039 c = DefaultContext.copy()
4040
4041 # prec, Emax
4042 for attr in ['prec', 'Emax']:
4043 setattr(c, attr, 999999)
4044 self.assertEqual(getattr(c, attr), 999999)
4045 self.assertRaises(ValueError, setattr, c, attr, -1)
4046 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
4047
4048 # Emin
4049 setattr(c, 'Emin', -999999)
4050 self.assertEqual(getattr(c, 'Emin'), -999999)
4051 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
4052 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
4053
Stefan Krah1919b7e2012-03-21 18:25:23 +01004054 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
4055 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
4056 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
4057 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
4058
4059 # capitals, clamp
4060 for attr in ['capitals', 'clamp']:
4061 self.assertRaises(ValueError, setattr, c, attr, -1)
4062 self.assertRaises(ValueError, setattr, c, attr, 2)
4063 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4064
4065 # Invalid attribute
4066 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4067
4068 # Invalid signal dict
4069 self.assertRaises(TypeError, setattr, c, 'flags', [])
4070 self.assertRaises(KeyError, setattr, c, 'flags', {})
4071 self.assertRaises(KeyError, setattr, c, 'traps',
4072 {'InvalidOperation':0})
4073
4074 # Attributes cannot be deleted
4075 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4076 'flags', 'traps']:
4077 self.assertRaises(AttributeError, c.__delattr__, attr)
4078
4079 # Invalid attributes
4080 self.assertRaises(TypeError, getattr, c, 9)
4081 self.assertRaises(TypeError, setattr, c, 9)
4082
4083 # Invalid values in constructor
4084 self.assertRaises(TypeError, Context, rounding=999999)
4085 self.assertRaises(TypeError, Context, rounding='xyz')
4086 self.assertRaises(ValueError, Context, clamp=2)
4087 self.assertRaises(ValueError, Context, capitals=-1)
4088 self.assertRaises(KeyError, Context, flags=["P"])
4089 self.assertRaises(KeyError, Context, traps=["Q"])
4090
4091 # Type error in conversion
4092 self.assertRaises(TypeError, Context, flags=(0,1))
4093 self.assertRaises(TypeError, Context, traps=(1,0))
4094
4095class CContextInputValidation(ContextInputValidation):
4096 decimal = C
4097class PyContextInputValidation(ContextInputValidation):
4098 decimal = P
4099
4100class ContextSubclassing(unittest.TestCase):
4101
4102 def test_context_subclassing(self):
4103 decimal = self.decimal
4104 Decimal = decimal.Decimal
4105 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004106 Clamped = decimal.Clamped
4107 DivisionByZero = decimal.DivisionByZero
4108 Inexact = decimal.Inexact
4109 Overflow = decimal.Overflow
4110 Rounded = decimal.Rounded
4111 Subnormal = decimal.Subnormal
4112 Underflow = decimal.Underflow
4113 InvalidOperation = decimal.InvalidOperation
4114
4115 class MyContext(Context):
4116 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4117 capitals=None, clamp=None, flags=None,
4118 traps=None):
4119 Context.__init__(self)
4120 if prec is not None:
4121 self.prec = prec
4122 if rounding is not None:
4123 self.rounding = rounding
4124 if Emin is not None:
4125 self.Emin = Emin
4126 if Emax is not None:
4127 self.Emax = Emax
4128 if capitals is not None:
4129 self.capitals = capitals
4130 if clamp is not None:
4131 self.clamp = clamp
4132 if flags is not None:
4133 if isinstance(flags, list):
4134 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4135 self.flags = flags
4136 if traps is not None:
4137 if isinstance(traps, list):
4138 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4139 self.traps = traps
4140
4141 c = Context()
4142 d = MyContext()
4143 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4144 'flags', 'traps'):
4145 self.assertEqual(getattr(c, attr), getattr(d, attr))
4146
4147 # prec
4148 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4149 c = MyContext(prec=1)
4150 self.assertEqual(c.prec, 1)
4151 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4152
4153 # rounding
4154 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4155 c = MyContext(rounding=ROUND_DOWN, prec=1)
4156 self.assertEqual(c.rounding, ROUND_DOWN)
4157 self.assertEqual(c.plus(Decimal('9.9')), 9)
4158
4159 # Emin
4160 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4161 c = MyContext(Emin=-1, prec=1)
4162 self.assertEqual(c.Emin, -1)
4163 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4164 self.assertEqual(x, Decimal('0.0'))
4165 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4166 self.assertTrue(c.flags[signal])
4167
4168 # Emax
4169 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4170 c = MyContext(Emax=1, prec=1)
4171 self.assertEqual(c.Emax, 1)
4172 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4173 if self.decimal == C:
4174 for signal in (Inexact, Overflow, Rounded):
4175 self.assertTrue(c.flags[signal])
4176
4177 # capitals
4178 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4179 c = MyContext(capitals=0)
4180 self.assertEqual(c.capitals, 0)
4181 x = c.create_decimal('1E222')
4182 self.assertEqual(c.to_sci_string(x), '1e+222')
4183
4184 # clamp
4185 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4186 c = MyContext(clamp=1, Emax=99)
4187 self.assertEqual(c.clamp, 1)
4188 x = c.plus(Decimal('1e99'))
4189 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4190
4191 # flags
4192 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4193 c = MyContext(flags=[Rounded, DivisionByZero])
4194 for signal in (Rounded, DivisionByZero):
4195 self.assertTrue(c.flags[signal])
4196 c.clear_flags()
4197 for signal in OrderedSignals[decimal]:
4198 self.assertFalse(c.flags[signal])
4199
4200 # traps
4201 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4202 c = MyContext(traps=[Rounded, DivisionByZero])
4203 for signal in (Rounded, DivisionByZero):
4204 self.assertTrue(c.traps[signal])
4205 c.clear_traps()
4206 for signal in OrderedSignals[decimal]:
4207 self.assertFalse(c.traps[signal])
4208
4209class CContextSubclassing(ContextSubclassing):
4210 decimal = C
4211class PyContextSubclassing(ContextSubclassing):
4212 decimal = P
4213
4214@skip_if_extra_functionality
4215class CheckAttributes(unittest.TestCase):
4216
4217 def test_module_attributes(self):
4218
4219 # Architecture dependent context limits
4220 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4221 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4222 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4223 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4224
4225 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4226 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4227
4228 self.assertEqual(C.__version__, P.__version__)
4229
Stefan Krahb578f8a2014-09-10 17:58:15 +02004230 self.assertEqual(dir(C), dir(P))
Stefan Krah1919b7e2012-03-21 18:25:23 +01004231
4232 def test_context_attributes(self):
4233
4234 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4235 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4236 self.assertEqual(set(x) - set(y), set())
4237
4238 def test_decimal_attributes(self):
4239
4240 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4241 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4242 self.assertEqual(set(x) - set(y), set())
4243
4244class Coverage(unittest.TestCase):
4245
4246 def test_adjusted(self):
4247 Decimal = self.decimal.Decimal
4248
4249 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4250 # XXX raise?
4251 self.assertEqual(Decimal('nan').adjusted(), 0)
4252 self.assertEqual(Decimal('inf').adjusted(), 0)
4253
4254 def test_canonical(self):
4255 Decimal = self.decimal.Decimal
4256 getcontext = self.decimal.getcontext
4257
4258 x = Decimal(9).canonical()
4259 self.assertEqual(x, 9)
4260
4261 c = getcontext()
4262 x = c.canonical(Decimal(9))
4263 self.assertEqual(x, 9)
4264
4265 def test_context_repr(self):
4266 c = self.decimal.DefaultContext.copy()
4267
4268 c.prec = 425000000
4269 c.Emax = 425000000
4270 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004271 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004272 c.capitals = 0
4273 c.clamp = 1
4274 for sig in OrderedSignals[self.decimal]:
4275 c.flags[sig] = False
4276 c.traps[sig] = False
4277
4278 s = c.__repr__()
4279 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4280 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4281 "flags=[], traps=[])"
4282 self.assertEqual(s, t)
4283
4284 def test_implicit_context(self):
4285 Decimal = self.decimal.Decimal
4286 localcontext = self.decimal.localcontext
4287
4288 with localcontext() as c:
4289 c.prec = 1
4290 c.Emax = 1
4291 c.Emin = -1
4292
4293 # abs
4294 self.assertEqual(abs(Decimal("-10")), 10)
4295 # add
4296 self.assertEqual(Decimal("7") + 1, 8)
4297 # divide
4298 self.assertEqual(Decimal("10") / 5, 2)
4299 # divide_int
4300 self.assertEqual(Decimal("10") // 7, 1)
4301 # fma
4302 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4303 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4304 # three arg power
4305 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4306 # exp
4307 self.assertEqual(Decimal("1.01").exp(), 3)
4308 # is_normal
4309 self.assertIs(Decimal("0.01").is_normal(), False)
4310 # is_subnormal
4311 self.assertIs(Decimal("0.01").is_subnormal(), True)
4312 # ln
4313 self.assertEqual(Decimal("20").ln(), 3)
4314 # log10
4315 self.assertEqual(Decimal("20").log10(), 1)
4316 # logb
4317 self.assertEqual(Decimal("580").logb(), 2)
4318 # logical_invert
4319 self.assertEqual(Decimal("10").logical_invert(), 1)
4320 # minus
4321 self.assertEqual(-Decimal("-10"), 10)
4322 # multiply
4323 self.assertEqual(Decimal("2") * 4, 8)
4324 # next_minus
4325 self.assertEqual(Decimal("10").next_minus(), 9)
4326 # next_plus
4327 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4328 # normalize
4329 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4330 # number_class
4331 self.assertEqual(Decimal("10").number_class(), '+Normal')
4332 # plus
4333 self.assertEqual(+Decimal("-1"), -1)
4334 # remainder
4335 self.assertEqual(Decimal("10") % 7, 3)
4336 # subtract
4337 self.assertEqual(Decimal("10") - 7, 3)
4338 # to_integral_exact
4339 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4340
4341 # Boolean functions
4342 self.assertTrue(Decimal("1").is_canonical())
4343 self.assertTrue(Decimal("1").is_finite())
4344 self.assertTrue(Decimal("1").is_finite())
4345 self.assertTrue(Decimal("snan").is_snan())
4346 self.assertTrue(Decimal("-1").is_signed())
4347 self.assertTrue(Decimal("0").is_zero())
4348 self.assertTrue(Decimal("0").is_zero())
4349
4350 # Copy
4351 with localcontext() as c:
4352 c.prec = 10000
4353 x = 1228 ** 1523
4354 y = -Decimal(x)
4355
4356 z = y.copy_abs()
4357 self.assertEqual(z, x)
4358
4359 z = y.copy_negate()
4360 self.assertEqual(z, x)
4361
4362 z = y.copy_sign(Decimal(1))
4363 self.assertEqual(z, x)
4364
4365 def test_divmod(self):
4366 Decimal = self.decimal.Decimal
4367 localcontext = self.decimal.localcontext
4368 InvalidOperation = self.decimal.InvalidOperation
4369 DivisionByZero = self.decimal.DivisionByZero
4370
4371 with localcontext() as c:
4372 q, r = divmod(Decimal("10912837129"), 1001)
4373 self.assertEqual(q, Decimal('10901935'))
4374 self.assertEqual(r, Decimal('194'))
4375
4376 q, r = divmod(Decimal("NaN"), 7)
4377 self.assertTrue(q.is_nan() and r.is_nan())
4378
4379 c.traps[InvalidOperation] = False
4380 q, r = divmod(Decimal("NaN"), 7)
4381 self.assertTrue(q.is_nan() and r.is_nan())
4382
4383 c.traps[InvalidOperation] = False
4384 c.clear_flags()
4385 q, r = divmod(Decimal("inf"), Decimal("inf"))
4386 self.assertTrue(q.is_nan() and r.is_nan())
4387 self.assertTrue(c.flags[InvalidOperation])
4388
4389 c.clear_flags()
4390 q, r = divmod(Decimal("inf"), 101)
4391 self.assertTrue(q.is_infinite() and r.is_nan())
4392 self.assertTrue(c.flags[InvalidOperation])
4393
4394 c.clear_flags()
4395 q, r = divmod(Decimal(0), 0)
4396 self.assertTrue(q.is_nan() and r.is_nan())
4397 self.assertTrue(c.flags[InvalidOperation])
4398
4399 c.traps[DivisionByZero] = False
4400 c.clear_flags()
4401 q, r = divmod(Decimal(11), 0)
4402 self.assertTrue(q.is_infinite() and r.is_nan())
4403 self.assertTrue(c.flags[InvalidOperation] and
4404 c.flags[DivisionByZero])
4405
4406 def test_power(self):
4407 Decimal = self.decimal.Decimal
4408 localcontext = self.decimal.localcontext
4409 Overflow = self.decimal.Overflow
4410 Rounded = self.decimal.Rounded
4411
4412 with localcontext() as c:
4413 c.prec = 3
4414 c.clear_flags()
4415 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4416 self.assertTrue(c.flags[Rounded])
4417
4418 c.prec = 1
4419 c.Emax = 1
4420 c.Emin = -1
4421 c.clear_flags()
4422 c.traps[Overflow] = False
4423 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4424 self.assertTrue(c.flags[Overflow])
4425
4426 def test_quantize(self):
4427 Decimal = self.decimal.Decimal
4428 localcontext = self.decimal.localcontext
4429 InvalidOperation = self.decimal.InvalidOperation
4430
4431 with localcontext() as c:
4432 c.prec = 1
4433 c.Emax = 1
4434 c.Emin = -1
4435 c.traps[InvalidOperation] = False
4436 x = Decimal(99).quantize(Decimal("1e1"))
4437 self.assertTrue(x.is_nan())
4438
4439 def test_radix(self):
4440 Decimal = self.decimal.Decimal
4441 getcontext = self.decimal.getcontext
4442
4443 c = getcontext()
4444 self.assertEqual(Decimal("1").radix(), 10)
4445 self.assertEqual(c.radix(), 10)
4446
4447 def test_rop(self):
4448 Decimal = self.decimal.Decimal
4449
4450 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4451 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4452 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4453
4454 def test_round(self):
4455 # Python3 behavior: round() returns Decimal
4456 Decimal = self.decimal.Decimal
Stefan Krahe95dfc52018-06-03 18:40:00 +02004457 localcontext = self.decimal.localcontext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004458
Stefan Krahe95dfc52018-06-03 18:40:00 +02004459 with localcontext() as c:
4460 c.prec = 28
Stefan Krah1919b7e2012-03-21 18:25:23 +01004461
Stefan Krahe95dfc52018-06-03 18:40:00 +02004462 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4463 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4464 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4465 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4466 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
Stefan Krah1919b7e2012-03-21 18:25:23 +01004467
Stefan Krahe95dfc52018-06-03 18:40:00 +02004468 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4469 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004470
4471 def test_create_decimal(self):
4472 c = self.decimal.Context()
4473 self.assertRaises(ValueError, c.create_decimal, ["%"])
4474
4475 def test_int(self):
4476 Decimal = self.decimal.Decimal
4477 localcontext = self.decimal.localcontext
4478
4479 with localcontext() as c:
4480 c.prec = 9999
4481 x = Decimal(1221**1271) / 10**3923
4482 self.assertEqual(int(x), 1)
4483 self.assertEqual(x.to_integral(), 2)
4484
4485 def test_copy(self):
4486 Context = self.decimal.Context
4487
4488 c = Context()
4489 c.prec = 10000
4490 x = -(1172 ** 1712)
4491
4492 y = c.copy_abs(x)
4493 self.assertEqual(y, -x)
4494
4495 y = c.copy_negate(x)
4496 self.assertEqual(y, -x)
4497
4498 y = c.copy_sign(x, 1)
4499 self.assertEqual(y, -x)
4500
4501class CCoverage(Coverage):
4502 decimal = C
4503class PyCoverage(Coverage):
4504 decimal = P
4505
4506class PyFunctionality(unittest.TestCase):
4507 """Extra functionality in decimal.py"""
4508
Stefan Krah1919b7e2012-03-21 18:25:23 +01004509 def test_py_alternate_formatting(self):
4510 # triples giving a format, a Decimal, and the expected result
4511 Decimal = P.Decimal
4512 localcontext = P.localcontext
4513
4514 test_values = [
4515 # Issue 7094: Alternate formatting (specified by #)
4516 ('.0e', '1.0', '1e+0'),
4517 ('#.0e', '1.0', '1.e+0'),
4518 ('.0f', '1.0', '1'),
4519 ('#.0f', '1.0', '1.'),
4520 ('g', '1.1', '1.1'),
4521 ('#g', '1.1', '1.1'),
4522 ('.0g', '1', '1'),
4523 ('#.0g', '1', '1.'),
4524 ('.0%', '1.0', '100%'),
4525 ('#.0%', '1.0', '100.%'),
4526 ]
4527 for fmt, d, result in test_values:
4528 self.assertEqual(format(Decimal(d), fmt), result)
4529
4530class PyWhitebox(unittest.TestCase):
4531 """White box testing for decimal.py"""
4532
4533 def test_py_exact_power(self):
4534 # Rarely exercised lines in _power_exact.
4535 Decimal = P.Decimal
4536 localcontext = P.localcontext
4537
4538 with localcontext() as c:
4539 c.prec = 8
4540 x = Decimal(2**16) ** Decimal("-0.5")
4541 self.assertEqual(x, Decimal('0.00390625'))
4542
4543 x = Decimal(2**16) ** Decimal("-0.6")
4544 self.assertEqual(x, Decimal('0.0012885819'))
4545
4546 x = Decimal("256e7") ** Decimal("-0.5")
4547
4548 x = Decimal(152587890625) ** Decimal('-0.0625')
4549 self.assertEqual(x, Decimal("0.2"))
4550
4551 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4552
4553 x = Decimal(5**2659) ** Decimal('-0.0625')
4554
4555 c.prec = 1
4556 x = Decimal("152587890625") ** Decimal('-0.5')
4557 c.prec = 201
4558 x = Decimal(2**578) ** Decimal("-0.5")
4559
4560 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004561 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004562 Decimal = P.Decimal
4563 DefaultContext = P.DefaultContext
4564 setcontext = P.setcontext
4565
4566 c = DefaultContext.copy()
4567 c.traps = dict((s, 0) for s in OrderedSignals[P])
4568 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004569
4570 d1 = Decimal('-25e55')
4571 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004572 d2 = Decimal('33e+33')
4573 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004574
4575 def checkSameDec(operation, useOther=False):
4576 if useOther:
4577 eval("d1." + operation + "(d2)")
4578 self.assertEqual(d1._sign, b1._sign)
4579 self.assertEqual(d1._int, b1._int)
4580 self.assertEqual(d1._exp, b1._exp)
4581 self.assertEqual(d2._sign, b2._sign)
4582 self.assertEqual(d2._int, b2._int)
4583 self.assertEqual(d2._exp, b2._exp)
4584 else:
4585 eval("d1." + operation + "()")
4586 self.assertEqual(d1._sign, b1._sign)
4587 self.assertEqual(d1._int, b1._int)
4588 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004589
4590 Decimal(d1)
4591 self.assertEqual(d1._sign, b1._sign)
4592 self.assertEqual(d1._int, b1._int)
4593 self.assertEqual(d1._exp, b1._exp)
4594
4595 checkSameDec("__abs__")
4596 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004597 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004598 checkSameDec("__eq__", True)
4599 checkSameDec("__ne__", True)
4600 checkSameDec("__le__", True)
4601 checkSameDec("__lt__", True)
4602 checkSameDec("__ge__", True)
4603 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004604 checkSameDec("__float__")
4605 checkSameDec("__floordiv__", True)
4606 checkSameDec("__hash__")
4607 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004608 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004609 checkSameDec("__mod__", True)
4610 checkSameDec("__mul__", True)
4611 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004612 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004613 checkSameDec("__pos__")
4614 checkSameDec("__pow__", True)
4615 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004616 checkSameDec("__rdivmod__", True)
4617 checkSameDec("__repr__")
4618 checkSameDec("__rfloordiv__", True)
4619 checkSameDec("__rmod__", True)
4620 checkSameDec("__rmul__", True)
4621 checkSameDec("__rpow__", True)
4622 checkSameDec("__rsub__", True)
4623 checkSameDec("__str__")
4624 checkSameDec("__sub__", True)
4625 checkSameDec("__truediv__", True)
4626 checkSameDec("adjusted")
4627 checkSameDec("as_tuple")
4628 checkSameDec("compare", True)
4629 checkSameDec("max", True)
4630 checkSameDec("min", True)
4631 checkSameDec("normalize")
4632 checkSameDec("quantize", True)
4633 checkSameDec("remainder_near", True)
4634 checkSameDec("same_quantum", True)
4635 checkSameDec("sqrt")
4636 checkSameDec("to_eng_string")
4637 checkSameDec("to_integral")
4638
Stefan Krah1919b7e2012-03-21 18:25:23 +01004639 def test_py_decimal_id(self):
4640 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004641
Stefan Krah1919b7e2012-03-21 18:25:23 +01004642 d = Decimal(45)
4643 e = Decimal(d)
4644 self.assertEqual(str(e), '45')
4645 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004646
Stefan Krah1919b7e2012-03-21 18:25:23 +01004647 def test_py_rescale(self):
4648 # Coverage
4649 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004650 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004651
Stefan Krah1919b7e2012-03-21 18:25:23 +01004652 with localcontext() as c:
4653 x = Decimal("NaN")._rescale(3, ROUND_UP)
4654 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004655
Stefan Krah1919b7e2012-03-21 18:25:23 +01004656 def test_py__round(self):
4657 # Coverage
4658 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004659
Stefan Krah1919b7e2012-03-21 18:25:23 +01004660 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004661
Stefan Krah1919b7e2012-03-21 18:25:23 +01004662class CFunctionality(unittest.TestCase):
4663 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004664
Stefan Krah1919b7e2012-03-21 18:25:23 +01004665 @requires_extra_functionality
4666 def test_c_ieee_context(self):
4667 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4668 IEEEContext = C.IEEEContext
4669 DECIMAL32 = C.DECIMAL32
4670 DECIMAL64 = C.DECIMAL64
4671 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004672
Stefan Krah1919b7e2012-03-21 18:25:23 +01004673 def assert_rest(self, context):
4674 self.assertEqual(context.clamp, 1)
4675 assert_signals(self, context, 'traps', [])
4676 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004677
Stefan Krah1919b7e2012-03-21 18:25:23 +01004678 c = IEEEContext(DECIMAL32)
4679 self.assertEqual(c.prec, 7)
4680 self.assertEqual(c.Emax, 96)
4681 self.assertEqual(c.Emin, -95)
4682 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004683
Stefan Krah1919b7e2012-03-21 18:25:23 +01004684 c = IEEEContext(DECIMAL64)
4685 self.assertEqual(c.prec, 16)
4686 self.assertEqual(c.Emax, 384)
4687 self.assertEqual(c.Emin, -383)
4688 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004689
Stefan Krah1919b7e2012-03-21 18:25:23 +01004690 c = IEEEContext(DECIMAL128)
4691 self.assertEqual(c.prec, 34)
4692 self.assertEqual(c.Emax, 6144)
4693 self.assertEqual(c.Emin, -6143)
4694 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004695
Stefan Krah1919b7e2012-03-21 18:25:23 +01004696 # Invalid values
4697 self.assertRaises(OverflowError, IEEEContext, 2**63)
4698 self.assertRaises(ValueError, IEEEContext, -1)
4699 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004700
Stefan Krah1919b7e2012-03-21 18:25:23 +01004701 @requires_extra_functionality
4702 def test_c_context(self):
4703 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004704
Stefan Krah1919b7e2012-03-21 18:25:23 +01004705 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4706 self.assertEqual(c._flags, C.DecClamped)
4707 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004708
Stefan Krah1919b7e2012-03-21 18:25:23 +01004709 @requires_extra_functionality
4710 def test_constants(self):
4711 # Condition flags
4712 cond = (
4713 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4714 C.DecDivisionImpossible, C.DecDivisionUndefined,
4715 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4716 C.DecInvalidOperation, C.DecMallocError,
4717 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4718 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004719 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004720
4721 # IEEEContext
4722 self.assertEqual(C.DECIMAL32, 32)
4723 self.assertEqual(C.DECIMAL64, 64)
4724 self.assertEqual(C.DECIMAL128, 128)
4725 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4726
Stefan Krah1919b7e2012-03-21 18:25:23 +01004727 # Conditions
4728 for i, v in enumerate(cond):
4729 self.assertEqual(v, 1<<i)
4730
4731 self.assertEqual(C.DecIEEEInvalidOperation,
4732 C.DecConversionSyntax|
4733 C.DecDivisionImpossible|
4734 C.DecDivisionUndefined|
4735 C.DecFpuError|
4736 C.DecInvalidContext|
4737 C.DecInvalidOperation|
4738 C.DecMallocError)
4739
4740 self.assertEqual(C.DecErrors,
4741 C.DecIEEEInvalidOperation|
4742 C.DecDivisionByZero)
4743
4744 self.assertEqual(C.DecTraps,
4745 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4746
4747class CWhitebox(unittest.TestCase):
4748 """Whitebox testing for _decimal"""
4749
4750 def test_bignum(self):
4751 # Not exactly whitebox, but too slow with pydecimal.
4752
4753 Decimal = C.Decimal
4754 localcontext = C.localcontext
4755
4756 b1 = 10**35
4757 b2 = 10**36
4758 with localcontext() as c:
4759 c.prec = 1000000
4760 for i in range(5):
4761 a = random.randrange(b1, b2)
4762 b = random.randrange(1000, 1200)
4763 x = a ** b
4764 y = Decimal(a) ** Decimal(b)
4765 self.assertEqual(x, y)
4766
4767 def test_invalid_construction(self):
4768 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4769
4770 def test_c_input_restriction(self):
4771 # Too large for _decimal to be converted exactly
4772 Decimal = C.Decimal
4773 InvalidOperation = C.InvalidOperation
4774 Context = C.Context
4775 localcontext = C.localcontext
4776
4777 with localcontext(Context()):
4778 self.assertRaises(InvalidOperation, Decimal,
4779 "1e9999999999999999999")
4780
4781 def test_c_context_repr(self):
4782 # This test is _decimal-only because flags are not printed
4783 # in the same order.
4784 DefaultContext = C.DefaultContext
4785 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004786
4787 c = DefaultContext.copy()
4788
4789 c.prec = 425000000
4790 c.Emax = 425000000
4791 c.Emin = -425000000
4792 c.rounding = ROUND_HALF_DOWN
4793 c.capitals = 0
4794 c.clamp = 1
4795 for sig in OrderedSignals[C]:
4796 c.flags[sig] = True
4797 c.traps[sig] = True
4798 c.flags[FloatOperation] = True
4799 c.traps[FloatOperation] = True
4800
4801 s = c.__repr__()
4802 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4803 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4804 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4805 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4806 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4807 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4808 self.assertEqual(s, t)
4809
4810 def test_c_context_errors(self):
4811 Context = C.Context
4812 InvalidOperation = C.InvalidOperation
4813 Overflow = C.Overflow
4814 FloatOperation = C.FloatOperation
4815 localcontext = C.localcontext
4816 getcontext = C.getcontext
4817 setcontext = C.setcontext
4818 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4819
4820 c = Context()
4821
4822 # SignalDict: input validation
4823 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4824 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4825 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4826 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4827 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4828 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4829 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4830 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4831
4832 # Test assignment from a signal dict with the correct length but
4833 # one invalid key.
4834 d = c.flags.copy()
4835 del d[FloatOperation]
4836 d["XYZ"] = 91283719
4837 self.assertRaises(KeyError, setattr, c, 'flags', d)
4838 self.assertRaises(KeyError, setattr, c, 'traps', d)
4839
4840 # Input corner cases
4841 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4842 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4843
4844 # prec, Emax, Emin
4845 for attr in ['prec', 'Emax']:
4846 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4847 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4848
4849 # prec, Emax, Emin in context constructor
4850 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4851 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4852 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4853
4854 # Overflow in conversion
4855 self.assertRaises(OverflowError, Context, prec=int_max+1)
4856 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4857 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004858 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4859 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4860
4861 # OverflowError, general ValueError
4862 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4863 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4864 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4865 if sys.platform != 'win32':
4866 self.assertRaises(ValueError, setattr, c, attr, int_max)
4867 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4868
Stefan Krah1919b7e2012-03-21 18:25:23 +01004869 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4870 if C.MAX_PREC == 425000000:
4871 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4872 int_max+1)
4873 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4874 int_max+1)
4875 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4876 -int_max-2)
4877
4878 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4879 if C.MAX_PREC == 425000000:
4880 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4881 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4882 1070000001)
4883 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4884 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4885 1070000001)
4886 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4887 -1070000001)
4888 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4889
4890 # capitals, clamp
4891 for attr in ['capitals', 'clamp']:
4892 self.assertRaises(ValueError, setattr, c, attr, -1)
4893 self.assertRaises(ValueError, setattr, c, attr, 2)
4894 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4895 if HAVE_CONFIG_64:
4896 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4897 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4898
4899 # Invalid local context
4900 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4901 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004902 self.assertRaises(TypeError, exec,
4903 'with localcontext(context=getcontext()): pass',
4904 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004905
4906 # setcontext
4907 saved_context = getcontext()
4908 self.assertRaises(TypeError, setcontext, "xyz")
4909 setcontext(saved_context)
4910
Stefan Krah59a4a932013-01-16 12:58:59 +01004911 def test_rounding_strings_interned(self):
4912
4913 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4914 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4915 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4916 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4917 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4918 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4919 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4920 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4921
Stefan Krah1919b7e2012-03-21 18:25:23 +01004922 @requires_extra_functionality
4923 def test_c_context_errors_extra(self):
4924 Context = C.Context
4925 InvalidOperation = C.InvalidOperation
4926 Overflow = C.Overflow
4927 localcontext = C.localcontext
4928 getcontext = C.getcontext
4929 setcontext = C.setcontext
4930 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4931
4932 c = Context()
4933
4934 # Input corner cases
4935 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4936
4937 # OverflowError, general ValueError
4938 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4939 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4940 if sys.platform != 'win32':
4941 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4942 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4943
4944 # OverflowError, general TypeError
4945 for attr in ('_flags', '_traps'):
4946 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4947 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4948 if sys.platform != 'win32':
4949 self.assertRaises(TypeError, setattr, c, attr, int_max)
4950 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4951
4952 # _allcr
4953 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4954 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4955 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4956 if HAVE_CONFIG_64:
4957 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4958 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4959
4960 # _flags, _traps
4961 for attr in ['_flags', '_traps']:
4962 self.assertRaises(TypeError, setattr, c, attr, 999999)
4963 self.assertRaises(TypeError, setattr, c, attr, 'x')
4964
4965 def test_c_valid_context(self):
4966 # These tests are for code coverage in _decimal.
4967 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004968 Clamped = C.Clamped
4969 Underflow = C.Underflow
4970 Inexact = C.Inexact
4971 Rounded = C.Rounded
4972 Subnormal = C.Subnormal
4973
4974 c = DefaultContext.copy()
4975
4976 # Exercise all getters and setters
4977 c.prec = 34
4978 c.rounding = ROUND_HALF_UP
4979 c.Emax = 3000
4980 c.Emin = -3000
4981 c.capitals = 1
4982 c.clamp = 0
4983
4984 self.assertEqual(c.prec, 34)
4985 self.assertEqual(c.rounding, ROUND_HALF_UP)
4986 self.assertEqual(c.Emin, -3000)
4987 self.assertEqual(c.Emax, 3000)
4988 self.assertEqual(c.capitals, 1)
4989 self.assertEqual(c.clamp, 0)
4990
4991 self.assertEqual(c.Etiny(), -3033)
4992 self.assertEqual(c.Etop(), 2967)
4993
4994 # Exercise all unsafe setters
4995 if C.MAX_PREC == 425000000:
4996 c._unsafe_setprec(999999999)
4997 c._unsafe_setemax(999999999)
4998 c._unsafe_setemin(-999999999)
4999 self.assertEqual(c.prec, 999999999)
5000 self.assertEqual(c.Emax, 999999999)
5001 self.assertEqual(c.Emin, -999999999)
5002
5003 @requires_extra_functionality
5004 def test_c_valid_context_extra(self):
5005 DefaultContext = C.DefaultContext
5006
5007 c = DefaultContext.copy()
5008 self.assertEqual(c._allcr, 1)
5009 c._allcr = 0
5010 self.assertEqual(c._allcr, 0)
5011
5012 def test_c_round(self):
5013 # Restricted input.
5014 Decimal = C.Decimal
5015 InvalidOperation = C.InvalidOperation
5016 localcontext = C.localcontext
5017 MAX_EMAX = C.MAX_EMAX
5018 MIN_ETINY = C.MIN_ETINY
5019 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
5020
5021 with localcontext() as c:
5022 c.traps[InvalidOperation] = True
5023 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5024 -int_max-1)
5025 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5026 int_max)
5027 self.assertRaises(InvalidOperation, Decimal("1").__round__,
5028 int(MAX_EMAX+1))
5029 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
5030 -int(MIN_ETINY-1))
5031 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5032 -int_max-2)
5033 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5034 int_max+1)
5035
5036 def test_c_format(self):
5037 # Restricted input
5038 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01005039 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5040
5041 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
5042 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
5043 self.assertRaises(TypeError, Decimal(1).__format__, [])
5044
Stefan Kraheb8c4512013-01-24 15:22:33 +01005045 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
5046 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
5047 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
5048 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005049
5050 def test_c_integral(self):
5051 Decimal = C.Decimal
5052 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01005053 localcontext = C.localcontext
5054
5055 x = Decimal(10)
5056 self.assertEqual(x.to_integral(), 10)
5057 self.assertRaises(TypeError, x.to_integral, '10')
5058 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5059 self.assertRaises(TypeError, x.to_integral, 10)
5060
5061 self.assertEqual(x.to_integral_value(), 10)
5062 self.assertRaises(TypeError, x.to_integral_value, '10')
5063 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5064 self.assertRaises(TypeError, x.to_integral_value, 10)
5065
5066 self.assertEqual(x.to_integral_exact(), 10)
5067 self.assertRaises(TypeError, x.to_integral_exact, '10')
5068 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5069 self.assertRaises(TypeError, x.to_integral_exact, 10)
5070
5071 with localcontext() as c:
5072 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5073 self.assertEqual(x, Decimal('100000000000000000000000000'))
5074
5075 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5076 self.assertEqual(x, Decimal('100000000000000000000000000'))
5077
5078 c.traps[Inexact] = True
5079 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5080
5081 def test_c_funcs(self):
5082 # Invalid arguments
5083 Decimal = C.Decimal
5084 InvalidOperation = C.InvalidOperation
5085 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005086 getcontext = C.getcontext
5087 localcontext = C.localcontext
5088
5089 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5090
5091 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5092 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5093 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5094
Raymond Hettinger771ed762009-01-03 19:20:32 +00005095 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005096 TypeError,
5097 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005098 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005099 self.assertRaises(
5100 TypeError,
5101 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5102 )
5103 self.assertRaises(
5104 TypeError,
5105 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5106 )
5107 self.assertRaises(
5108 TypeError,
5109 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5110 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005111
Stefan Krah1919b7e2012-03-21 18:25:23 +01005112 with localcontext() as c:
5113 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005114
Stefan Krah1919b7e2012-03-21 18:25:23 +01005115 # Invalid arguments
5116 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5117 self.assertRaises(TypeError, c.canonical, 200)
5118 self.assertRaises(TypeError, c.is_canonical, 200)
5119 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5120 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005121
Stefan Krah1919b7e2012-03-21 18:25:23 +01005122 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5123 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005124
Stefan Krah1919b7e2012-03-21 18:25:23 +01005125 c.traps[DivisionByZero] = True
5126 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5127 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5128 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005129
Stefan Krah1919b7e2012-03-21 18:25:23 +01005130 c.clear_flags()
5131 c.traps[InvalidOperation] = True
5132 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5133 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5134 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005135
Stefan Krah1919b7e2012-03-21 18:25:23 +01005136 c.traps[InvalidOperation] = True
5137 c.prec = 2
5138 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005139
Stefan Krah040e3112012-12-15 22:33:33 +01005140 def test_va_args_exceptions(self):
5141 Decimal = C.Decimal
5142 Context = C.Context
5143
5144 x = Decimal("10001111111")
5145
5146 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5147 'logb', 'logical_invert', 'next_minus', 'next_plus',
5148 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5149 func = getattr(x, attr)
5150 self.assertRaises(TypeError, func, context="x")
5151 self.assertRaises(TypeError, func, "x", context=None)
5152
5153 for attr in ['compare', 'compare_signal', 'logical_and',
5154 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5155 'remainder_near', 'rotate', 'scaleb', 'shift']:
5156 func = getattr(x, attr)
5157 self.assertRaises(TypeError, func, context="x")
5158 self.assertRaises(TypeError, func, "x", context=None)
5159
5160 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5161 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5162 self.assertRaises(TypeError, x.to_integral, [], [])
5163
5164 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5165 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5166 self.assertRaises(TypeError, x.to_integral_value, [], [])
5167
5168 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5169 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5170 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5171
5172 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5173 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5174
5175 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5176 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5177 self.assertRaises(TypeError, x.quantize, 1, [], [])
5178
5179 c = Context()
5180 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5181 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5182 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5183
Stefan Krah1919b7e2012-03-21 18:25:23 +01005184 @requires_extra_functionality
5185 def test_c_context_templates(self):
5186 self.assertEqual(
5187 C.BasicContext._traps,
5188 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5189 C.DecUnderflow|C.DecClamped
5190 )
5191 self.assertEqual(
5192 C.DefaultContext._traps,
5193 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5194 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005195
Stefan Krah1919b7e2012-03-21 18:25:23 +01005196 @requires_extra_functionality
5197 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005198
Stefan Krah1919b7e2012-03-21 18:25:23 +01005199 # SignalDict coverage
5200 Context = C.Context
5201 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005202
Stefan Krah1919b7e2012-03-21 18:25:23 +01005203 InvalidOperation = C.InvalidOperation
5204 DivisionByZero = C.DivisionByZero
5205 Overflow = C.Overflow
5206 Subnormal = C.Subnormal
5207 Underflow = C.Underflow
5208 Rounded = C.Rounded
5209 Inexact = C.Inexact
5210 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005211
Stefan Krah1919b7e2012-03-21 18:25:23 +01005212 DecClamped = C.DecClamped
5213 DecInvalidOperation = C.DecInvalidOperation
5214 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005215
Stefan Krah1919b7e2012-03-21 18:25:23 +01005216 def assertIsExclusivelySet(signal, signal_dict):
5217 for sig in signal_dict:
5218 if sig == signal:
5219 self.assertTrue(signal_dict[sig])
5220 else:
5221 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005222
Stefan Krah1919b7e2012-03-21 18:25:23 +01005223 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005224
Stefan Krah1919b7e2012-03-21 18:25:23 +01005225 # Signal dict methods
5226 self.assertTrue(Overflow in c.traps)
5227 c.clear_traps()
5228 for k in c.traps.keys():
5229 c.traps[k] = True
5230 for v in c.traps.values():
5231 self.assertTrue(v)
5232 c.clear_traps()
5233 for k, v in c.traps.items():
5234 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005235
Stefan Krah1919b7e2012-03-21 18:25:23 +01005236 self.assertFalse(c.flags.get(Overflow))
5237 self.assertIs(c.flags.get("x"), None)
5238 self.assertEqual(c.flags.get("x", "y"), "y")
5239 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005240
Stefan Krah1919b7e2012-03-21 18:25:23 +01005241 self.assertEqual(len(c.flags), len(c.traps))
5242 s = sys.getsizeof(c.flags)
5243 s = sys.getsizeof(c.traps)
5244 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005245
Stefan Krah1919b7e2012-03-21 18:25:23 +01005246 # Set flags/traps.
5247 c.clear_flags()
5248 c._flags = DecClamped
5249 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005250
Stefan Krah1919b7e2012-03-21 18:25:23 +01005251 c.clear_traps()
5252 c._traps = DecInvalidOperation
5253 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005254
Stefan Krah1919b7e2012-03-21 18:25:23 +01005255 # Set flags/traps from dictionary.
5256 c.clear_flags()
5257 d = c.flags.copy()
5258 d[DivisionByZero] = True
5259 c.flags = d
5260 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005261
Stefan Krah1919b7e2012-03-21 18:25:23 +01005262 c.clear_traps()
5263 d = c.traps.copy()
5264 d[Underflow] = True
5265 c.traps = d
5266 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005267
Stefan Krah1919b7e2012-03-21 18:25:23 +01005268 # Random constructors
5269 IntSignals = {
5270 Clamped: C.DecClamped,
5271 Rounded: C.DecRounded,
5272 Inexact: C.DecInexact,
5273 Subnormal: C.DecSubnormal,
5274 Underflow: C.DecUnderflow,
5275 Overflow: C.DecOverflow,
5276 DivisionByZero: C.DecDivisionByZero,
5277 InvalidOperation: C.DecIEEEInvalidOperation
5278 }
5279 IntCond = [
5280 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5281 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5282 C.DecConversionSyntax,
5283 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005284
Stefan Krah1919b7e2012-03-21 18:25:23 +01005285 lim = len(OrderedSignals[C])
5286 for r in range(lim):
5287 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005288 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005289 flags = random.sample(OrderedSignals[C], r)
5290 traps = random.sample(OrderedSignals[C], t)
5291 prec = random.randrange(1, 10000)
5292 emin = random.randrange(-10000, 0)
5293 emax = random.randrange(0, 10000)
5294 clamp = random.randrange(0, 2)
5295 caps = random.randrange(0, 2)
5296 cr = random.randrange(0, 2)
5297 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5298 capitals=caps, clamp=clamp, flags=list(flags),
5299 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005300
Stefan Krah1919b7e2012-03-21 18:25:23 +01005301 self.assertEqual(c.prec, prec)
5302 self.assertEqual(c.rounding, round)
5303 self.assertEqual(c.Emin, emin)
5304 self.assertEqual(c.Emax, emax)
5305 self.assertEqual(c.capitals, caps)
5306 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005307
Stefan Krah1919b7e2012-03-21 18:25:23 +01005308 f = 0
5309 for x in flags:
5310 f |= IntSignals[x]
5311 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005312
Stefan Krah1919b7e2012-03-21 18:25:23 +01005313 f = 0
5314 for x in traps:
5315 f |= IntSignals[x]
5316 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005317
Stefan Krah1919b7e2012-03-21 18:25:23 +01005318 for cond in IntCond:
5319 c._flags = cond
5320 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5321 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005322
Stefan Krah1919b7e2012-03-21 18:25:23 +01005323 for cond in IntCond:
5324 c._traps = cond
5325 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5326 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005327
Stefan Krah1919b7e2012-03-21 18:25:23 +01005328 def test_invalid_override(self):
5329 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005330
Stefan Krah1919b7e2012-03-21 18:25:23 +01005331 try:
5332 from locale import CHAR_MAX
5333 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06005334 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson84230a12010-02-18 14:49:50 +00005335
Stefan Krah1919b7e2012-03-21 18:25:23 +01005336 def make_grouping(lst):
5337 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005338
Stefan Krah1919b7e2012-03-21 18:25:23 +01005339 def get_fmt(x, override=None, fmt='n'):
5340 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005341
Stefan Krah1919b7e2012-03-21 18:25:23 +01005342 invalid_grouping = {
5343 'decimal_point' : ',',
5344 'grouping' : make_grouping([255, 255, 0]),
5345 'thousands_sep' : ','
5346 }
5347 invalid_dot = {
5348 'decimal_point' : 'xxxxx',
5349 'grouping' : make_grouping([3, 3, 0]),
5350 'thousands_sep' : ','
5351 }
5352 invalid_sep = {
5353 'decimal_point' : '.',
5354 'grouping' : make_grouping([3, 3, 0]),
5355 'thousands_sep' : 'yyyyy'
5356 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005357
Stefan Krah1919b7e2012-03-21 18:25:23 +01005358 if CHAR_MAX == 127: # negative grouping in override
5359 self.assertRaises(ValueError, get_fmt, 12345,
5360 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005361
Stefan Krah1919b7e2012-03-21 18:25:23 +01005362 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5363 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005364
Stefan Krah0774e9b2012-04-05 15:21:58 +02005365 def test_exact_conversion(self):
5366 Decimal = C.Decimal
5367 localcontext = C.localcontext
5368 InvalidOperation = C.InvalidOperation
5369
5370 with localcontext() as c:
5371
5372 c.traps[InvalidOperation] = True
5373
5374 # Clamped
5375 x = "0e%d" % sys.maxsize
5376 self.assertRaises(InvalidOperation, Decimal, x)
5377
5378 x = "0e%d" % (-sys.maxsize-1)
5379 self.assertRaises(InvalidOperation, Decimal, x)
5380
5381 # Overflow
5382 x = "1e%d" % sys.maxsize
5383 self.assertRaises(InvalidOperation, Decimal, x)
5384
5385 # Underflow
5386 x = "1e%d" % (-sys.maxsize-1)
5387 self.assertRaises(InvalidOperation, Decimal, x)
5388
Stefan Krahff3eca02012-04-05 15:46:19 +02005389 def test_from_tuple(self):
5390 Decimal = C.Decimal
5391 localcontext = C.localcontext
5392 InvalidOperation = C.InvalidOperation
5393 Overflow = C.Overflow
5394 Underflow = C.Underflow
5395
5396 with localcontext() as c:
5397
5398 c.traps[InvalidOperation] = True
5399 c.traps[Overflow] = True
5400 c.traps[Underflow] = True
5401
5402 # SSIZE_MAX
5403 x = (1, (), sys.maxsize)
5404 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5405 self.assertRaises(InvalidOperation, Decimal, x)
5406
5407 x = (1, (0, 1, 2), sys.maxsize)
5408 self.assertRaises(Overflow, c.create_decimal, x)
5409 self.assertRaises(InvalidOperation, Decimal, x)
5410
5411 # SSIZE_MIN
5412 x = (1, (), -sys.maxsize-1)
Stefan Krahe95dfc52018-06-03 18:40:00 +02005413 self.assertEqual(str(c.create_decimal(x)), '-0E-1000007')
Stefan Krahff3eca02012-04-05 15:46:19 +02005414 self.assertRaises(InvalidOperation, Decimal, x)
5415
5416 x = (1, (0, 1, 2), -sys.maxsize-1)
5417 self.assertRaises(Underflow, c.create_decimal, x)
5418 self.assertRaises(InvalidOperation, Decimal, x)
5419
5420 # OverflowError
5421 x = (1, (), sys.maxsize+1)
5422 self.assertRaises(OverflowError, c.create_decimal, x)
5423 self.assertRaises(OverflowError, Decimal, x)
5424
5425 x = (1, (), -sys.maxsize-2)
5426 self.assertRaises(OverflowError, c.create_decimal, x)
5427 self.assertRaises(OverflowError, Decimal, x)
5428
5429 # Specials
5430 x = (1, (), "N")
5431 self.assertEqual(str(Decimal(x)), '-sNaN')
5432 x = (1, (0,), "N")
5433 self.assertEqual(str(Decimal(x)), '-sNaN')
5434 x = (1, (0, 1), "N")
5435 self.assertEqual(str(Decimal(x)), '-sNaN1')
5436
Stefan Krah891ca9e2013-05-29 19:14:17 +02005437 def test_sizeof(self):
5438 Decimal = C.Decimal
5439 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5440
5441 self.assertGreater(Decimal(0).__sizeof__(), 0)
5442 if HAVE_CONFIG_64:
5443 x = Decimal(10**(19*24)).__sizeof__()
5444 y = Decimal(10**(19*25)).__sizeof__()
5445 self.assertEqual(y, x+8)
5446 else:
5447 x = Decimal(10**(9*24)).__sizeof__()
5448 y = Decimal(10**(9*25)).__sizeof__()
5449 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005450
Stefan Krah8c126f12016-07-17 14:01:42 +02005451 def test_internal_use_of_overridden_methods(self):
5452 Decimal = C.Decimal
5453
5454 # Unsound subtyping
5455 class X(float):
5456 def as_integer_ratio(self):
5457 return 1
5458 def __abs__(self):
5459 return self
5460
5461 class Y(float):
5462 def __abs__(self):
5463 return [1]*200
5464
5465 class I(int):
5466 def bit_length(self):
5467 return [1]*200
5468
5469 class Z(float):
5470 def as_integer_ratio(self):
5471 return (I(1), I(1))
5472 def __abs__(self):
5473 return self
5474
5475 for cls in X, Y, Z:
5476 self.assertEqual(Decimal.from_float(cls(101.1)),
5477 Decimal.from_float(101.1))
5478
Stefan Krah6b794b82014-05-01 17:42:33 +02005479@requires_docstrings
5480@unittest.skipUnless(C, "test requires C version")
Stefan Krah5de1f822014-05-01 15:53:42 +02005481class SignatureTest(unittest.TestCase):
5482 """Function signatures"""
5483
5484 def test_inspect_module(self):
5485 for attr in dir(P):
5486 if attr.startswith('_'):
5487 continue
5488 p_func = getattr(P, attr)
5489 c_func = getattr(C, attr)
5490 if (attr == 'Decimal' or attr == 'Context' or
5491 inspect.isfunction(p_func)):
5492 p_sig = inspect.signature(p_func)
5493 c_sig = inspect.signature(c_func)
5494
5495 # parameter names:
5496 c_names = list(c_sig.parameters.keys())
5497 p_names = [x for x in p_sig.parameters.keys() if not
5498 x.startswith('_')]
5499
5500 self.assertEqual(c_names, p_names,
5501 msg="parameter name mismatch in %s" % p_func)
5502
5503 c_kind = [x.kind for x in c_sig.parameters.values()]
5504 p_kind = [x[1].kind for x in p_sig.parameters.items() if not
5505 x[0].startswith('_')]
5506
5507 # parameters:
5508 if attr != 'setcontext':
5509 self.assertEqual(c_kind, p_kind,
5510 msg="parameter kind mismatch in %s" % p_func)
5511
5512 def test_inspect_types(self):
5513
5514 POS = inspect._ParameterKind.POSITIONAL_ONLY
5515 POS_KWD = inspect._ParameterKind.POSITIONAL_OR_KEYWORD
5516
5517 # Type heuristic (type annotations would help!):
5518 pdict = {C: {'other': C.Decimal(1),
5519 'third': C.Decimal(1),
5520 'x': C.Decimal(1),
5521 'y': C.Decimal(1),
5522 'z': C.Decimal(1),
5523 'a': C.Decimal(1),
5524 'b': C.Decimal(1),
5525 'c': C.Decimal(1),
5526 'exp': C.Decimal(1),
5527 'modulo': C.Decimal(1),
5528 'num': "1",
5529 'f': 1.0,
5530 'rounding': C.ROUND_HALF_UP,
5531 'context': C.getcontext()},
5532 P: {'other': P.Decimal(1),
5533 'third': P.Decimal(1),
5534 'a': P.Decimal(1),
5535 'b': P.Decimal(1),
5536 'c': P.Decimal(1),
5537 'exp': P.Decimal(1),
5538 'modulo': P.Decimal(1),
5539 'num': "1",
5540 'f': 1.0,
5541 'rounding': P.ROUND_HALF_UP,
5542 'context': P.getcontext()}}
5543
5544 def mkargs(module, sig):
5545 args = []
5546 kwargs = {}
5547 for name, param in sig.parameters.items():
5548 if name == 'self': continue
5549 if param.kind == POS:
5550 args.append(pdict[module][name])
5551 elif param.kind == POS_KWD:
5552 kwargs[name] = pdict[module][name]
5553 else:
5554 raise TestFailed("unexpected parameter kind")
5555 return args, kwargs
5556
5557 def tr(s):
5558 """The C Context docstrings use 'x' in order to prevent confusion
5559 with the article 'a' in the descriptions."""
5560 if s == 'x': return 'a'
5561 if s == 'y': return 'b'
5562 if s == 'z': return 'c'
5563 return s
5564
5565 def doit(ty):
5566 p_type = getattr(P, ty)
5567 c_type = getattr(C, ty)
5568 for attr in dir(p_type):
5569 if attr.startswith('_'):
5570 continue
5571 p_func = getattr(p_type, attr)
5572 c_func = getattr(c_type, attr)
5573 if inspect.isfunction(p_func):
5574 p_sig = inspect.signature(p_func)
5575 c_sig = inspect.signature(c_func)
5576
5577 # parameter names:
5578 p_names = list(p_sig.parameters.keys())
5579 c_names = [tr(x) for x in c_sig.parameters.keys()]
5580
5581 self.assertEqual(c_names, p_names,
5582 msg="parameter name mismatch in %s" % p_func)
5583
5584 p_kind = [x.kind for x in p_sig.parameters.values()]
5585 c_kind = [x.kind for x in c_sig.parameters.values()]
5586
5587 # 'self' parameter:
5588 self.assertIs(p_kind[0], POS_KWD)
5589 self.assertIs(c_kind[0], POS)
5590
5591 # remaining parameters:
5592 if ty == 'Decimal':
5593 self.assertEqual(c_kind[1:], p_kind[1:],
5594 msg="parameter kind mismatch in %s" % p_func)
5595 else: # Context methods are positional only in the C version.
5596 self.assertEqual(len(c_kind), len(p_kind),
5597 msg="parameter kind mismatch in %s" % p_func)
5598
5599 # Run the function:
5600 args, kwds = mkargs(C, c_sig)
5601 try:
5602 getattr(c_type(9), attr)(*args, **kwds)
5603 except Exception as err:
5604 raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds))
5605
5606 args, kwds = mkargs(P, p_sig)
5607 try:
5608 getattr(p_type(9), attr)(*args, **kwds)
5609 except Exception as err:
5610 raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds))
5611
5612 doit('Decimal')
5613 doit('Context')
5614
5615
Stefan Krah1919b7e2012-03-21 18:25:23 +01005616all_tests = [
5617 CExplicitConstructionTest, PyExplicitConstructionTest,
5618 CImplicitConstructionTest, PyImplicitConstructionTest,
5619 CFormatTest, PyFormatTest,
5620 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5621 CThreadingTest, PyThreadingTest,
5622 CUsabilityTest, PyUsabilityTest,
5623 CPythonAPItests, PyPythonAPItests,
5624 CContextAPItests, PyContextAPItests,
5625 CContextWithStatement, PyContextWithStatement,
5626 CContextFlags, PyContextFlags,
5627 CSpecialContexts, PySpecialContexts,
5628 CContextInputValidation, PyContextInputValidation,
5629 CContextSubclassing, PyContextSubclassing,
5630 CCoverage, PyCoverage,
5631 CFunctionality, PyFunctionality,
5632 CWhitebox, PyWhitebox,
5633 CIBMTestCases, PyIBMTestCases,
5634]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005635
Stefan Krah1919b7e2012-03-21 18:25:23 +01005636# Delete C tests if _decimal.so is not present.
5637if not C:
5638 all_tests = all_tests[1::2]
5639else:
5640 all_tests.insert(0, CheckAttributes)
Stefan Krah5de1f822014-05-01 15:53:42 +02005641 all_tests.insert(1, SignatureTest)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005642
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005643
Zachary Ware66f29282014-06-02 16:01:29 -05005644def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005645 """ Execute the tests.
5646
Raymond Hettingered20ad82004-09-04 20:09:13 +00005647 Runs all arithmetic tests if arith is True or if the "decimal" resource
5648 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005649 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005650
Stefan Krah1919b7e2012-03-21 18:25:23 +01005651 init(C)
5652 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005653 global TEST_ALL, DEBUG
Zachary Ware66f29282014-06-02 16:01:29 -05005654 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005655 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005656
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005657 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005658 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005659 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005660 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005661
5662 # Dynamically build custom test definition for each file in the test
5663 # directory and add the definitions to the DecimalTest class. This
5664 # procedure insures that new files do not get skipped.
5665 for filename in os.listdir(directory):
5666 if '.decTest' not in filename or filename.startswith("."):
5667 continue
5668 head, tail = filename.split('.')
5669 if todo_tests is not None and head not in todo_tests:
5670 continue
5671 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005672 setattr(CIBMTestCases, 'test_' + head, tester)
5673 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005674 del filename, head, tail, tester
5675
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005676
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005677 try:
5678 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005679 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005680 from doctest import IGNORE_EXCEPTION_DETAIL
5681 savedecimal = sys.modules['decimal']
5682 if C:
5683 sys.modules['decimal'] = C
5684 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5685 sys.modules['decimal'] = P
5686 run_doctest(P, verbose)
5687 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005688 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005689 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5690 P.setcontext(ORIGINAL_CONTEXT[P])
5691 if not C:
5692 warnings.warn('C tests skipped: no module named _decimal.',
5693 UserWarning)
5694 if not orig_sys_decimal is sys.modules['decimal']:
5695 raise TestFailed("Internal error: unbalanced number of changes to "
5696 "sys.modules['decimal'].")
5697
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005698
5699if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005700 import optparse
5701 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5702 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5703 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5704 (opt, args) = p.parse_args()
5705
5706 if opt.skip:
5707 test_main(arith=False, verbose=True)
5708 elif args:
5709 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005710 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005711 test_main(arith=True, verbose=True)