Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(45310)

Side by Side Diff: Lib/test/test_decimal.py

Issue 7652: Merge C version of decimal into py3k.
Patch Set: Created 7 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Lib/test/support.py ('k') | Lib/test/test_fractions.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2004 Python Software Foundation. 1 # Copyright (c) 2004 Python Software Foundation.
2 # All rights reserved. 2 # All rights reserved.
3 3
4 # Written by Eric Price <eprice at tjhsst.edu> 4 # Written by Eric Price <eprice at tjhsst.edu>
5 # and Facundo Batista <facundo at taniquetil.com.ar> 5 # and Facundo Batista <facundo at taniquetil.com.ar>
6 # and Raymond Hettinger <python at rcn.com> 6 # and Raymond Hettinger <python at rcn.com>
7 # and Aahz (aahz at pobox.com) 7 # and Aahz (aahz at pobox.com)
8 # and Tim Peters 8 # and Tim Peters
9 9
10 """ 10 """
11 These are the test cases for the Decimal module. 11 These are the test cases for the Decimal module.
12 12
13 There are two groups of tests, Arithmetic and Behaviour. The former test 13 There are two groups of tests, Arithmetic and Behaviour. The former test
14 the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter 14 the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
15 test the pythonic behaviour according to PEP 327. 15 test the pythonic behaviour according to PEP 327.
16 16
17 Cowlishaw's tests can be downloaded from: 17 Cowlishaw's tests can be downloaded from:
18 18
19 www2.hursley.ibm.com/decimal/dectest.zip 19 http://speleotrove.com/decimal/dectest.zip
20 20
21 This test module can be called from command line with one parameter (Arithmetic 21 This test module can be called from command line with one parameter (Arithmetic
22 or Behaviour) to test each part, or without parameter to test both parts. If 22 or Behaviour) to test each part, or without parameter to test both parts. If
23 you're working through IDLE, you can import this test module and call test_main( ) 23 you're working through IDLE, you can import this test module and call test_main( )
24 with the corresponding argument. 24 with the corresponding argument.
25 """ 25 """
26 26
27 import math 27 import math
28 import os, sys 28 import os, sys
29 import operator 29 import operator
30 import warnings 30 import warnings
31 import pickle, copy 31 import pickle, copy
32 import unittest 32 import unittest
33 from decimal import *
34 import numbers 33 import numbers
34 import locale
35 from test.support import (run_unittest, run_doctest, is_resource_enabled, 35 from test.support import (run_unittest, run_doctest, is_resource_enabled,
36 requires_IEEE_754) 36 requires_IEEE_754)
37 from test.support import check_warnings 37 from test.support import check_warnings, import_fresh_module, TestFailed
38 import random 38 import random
39 import time
40 import warnings
39 try: 41 try:
40 import threading 42 import threading
41 except ImportError: 43 except ImportError:
42 threading = None 44 threading = None
43 45
46
47 C = import_fresh_module('decimal', fresh=['_decimal'])
48 P = import_fresh_module('decimal', blocked=['_decimal'])
49 orig_sys_decimal = sys.modules['decimal']
50
51 # fractions module must import the correct decimal module.
52 cfractions = import_fresh_module('fractions', fresh=['fractions'])
53 sys.modules['decimal'] = P
54 pfractions = import_fresh_module('fractions', fresh=['fractions'])
55 sys.modules['decimal'] = C
56 fractions = {C:cfractions, P:pfractions}
57 sys.modules['decimal'] = orig_sys_decimal
58
59
44 # Useful Test Constant 60 # Useful Test Constant
45 Signals = tuple(getcontext().flags.keys()) 61 Signals = {
46 62 C: tuple(C.getcontext().flags.keys()) if C else None,
63 P: tuple(P.getcontext().flags.keys())
64 }
47 # Signals ordered with respect to precedence: when an operation 65 # Signals ordered with respect to precedence: when an operation
48 # produces multiple signals, signals occurring later in the list 66 # produces multiple signals, signals occurring later in the list
49 # should be handled before those occurring earlier in the list. 67 # should be handled before those occurring earlier in the list.
50 OrderedSignals = (Clamped, Rounded, Inexact, Subnormal, 68 OrderedSignals = {
51 Underflow, Overflow, DivisionByZero, InvalidOperation) 69 C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow,
70 C.Overflow, C.DivisionByZero, C.InvalidOperation] if C else None,
71 P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow,
72 P.Overflow, P.DivisionByZero, P.InvalidOperation]
73 }
74 def assert_signals(cls, context, attr, expected):
75 d = getattr(context, attr)
76 cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
77
78 RoundingModes = {
79 C: (C.ROUND_UP, C.ROUND_DOWN, C.ROUND_CEILING, C.ROUND_FLOOR,
80 C.ROUND_HALF_UP, C.ROUND_HALF_DOWN, C.ROUND_HALF_EVEN,
81 C.ROUND_05UP) if C else None,
82 P: (P.ROUND_UP, P.ROUND_DOWN, P.ROUND_CEILING, P.ROUND_FLOOR,
83 P.ROUND_HALF_UP, P.ROUND_HALF_DOWN, P.ROUND_HALF_EVEN,
84 P.ROUND_05UP)
85 }
52 86
53 # Tests are built around these assumed context defaults. 87 # Tests are built around these assumed context defaults.
54 # test_main() restores the original context. 88 # test_main() restores the original context.
55 def init(): 89 ORIGINAL_CONTEXT = {
56 global ORIGINAL_CONTEXT 90 C: C.getcontext().copy() if C else None,
57 ORIGINAL_CONTEXT = getcontext().copy() 91 P: P.getcontext().copy()
58 DefaultTestContext = Context( 92 }
59 prec = 9, 93 def init(m):
60 rounding = ROUND_HALF_EVEN, 94 if not m: return
61 traps = dict.fromkeys(Signals, 0) 95 DefaultTestContext = m.Context(
62 ) 96 prec=9, rounding=m.ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
63 setcontext(DefaultTestContext) 97 )
98 m.setcontext(DefaultTestContext)
64 99
65 TESTDATADIR = 'decimaltestdata' 100 TESTDATADIR = 'decimaltestdata'
66 if __name__ == '__main__': 101 if __name__ == '__main__':
67 file = sys.argv[0] 102 file = sys.argv[0]
68 else: 103 else:
69 file = __file__ 104 file = __file__
70 testdir = os.path.dirname(file) or os.curdir 105 testdir = os.path.dirname(file) or os.curdir
71 directory = testdir + os.sep + TESTDATADIR + os.sep 106 directory = testdir + os.sep + TESTDATADIR + os.sep
72 107
73 skip_expected = not os.path.isdir(directory) 108 skip_expected = not os.path.isdir(directory)
74
75 # list of individual .decTest test ids that correspond to tests that
76 # we're skipping for one reason or another.
77 skipped_test_ids = set([
78 # Skip implementation-specific scaleb tests.
79 'scbx164',
80 'scbx165',
81
82 # For some operations (currently exp, ln, log10, power), the decNumber
83 # reference implementation imposes additional restrictions on the context
84 # and operands. These restrictions are not part of the specification;
85 # however, the effect of these restrictions does show up in some of the
86 # testcases. We skip testcases that violate these restrictions, since
87 # Decimal behaves differently from decNumber for these testcases so these
88 # testcases would otherwise fail.
89 'expx901',
90 'expx902',
91 'expx903',
92 'expx905',
93 'lnx901',
94 'lnx902',
95 'lnx903',
96 'lnx905',
97 'logx901',
98 'logx902',
99 'logx903',
100 'logx905',
101 'powx1183',
102 'powx1184',
103 'powx4001',
104 'powx4002',
105 'powx4003',
106 'powx4005',
107 'powx4008',
108 'powx4010',
109 'powx4012',
110 'powx4014',
111 ])
112 109
113 # Make sure it actually raises errors when not expected and caught in flags 110 # Make sure it actually raises errors when not expected and caught in flags
114 # Slower, since it runs some things several times. 111 # Slower, since it runs some things several times.
115 EXTENDEDERRORTEST = False 112 EXTENDEDERRORTEST = False
116 113
117 #Map the test cases' error names to the actual errors 114 # Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
118 ErrorNames = {'clamped' : Clamped, 115 EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
119 'conversion_syntax' : InvalidOperation, 116 requires_extra_functionality = unittest.skipUnless(
120 'division_by_zero' : DivisionByZero, 117 EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
121 'division_impossible' : InvalidOperation,
122 'division_undefined' : InvalidOperation,
123 'inexact' : Inexact,
124 'invalid_context' : InvalidOperation,
125 'invalid_operation' : InvalidOperation,
126 'overflow' : Overflow,
127 'rounded' : Rounded,
128 'subnormal' : Subnormal,
129 'underflow' : Underflow}
130 118
131 119
132 def Nonfunction(*args): 120 class IBMTestCases(unittest.TestCase):
133 """Doesn't do anything.""" 121 """Class which tests the Decimal class against the IBM test cases."""
134 return None
135 122
136 RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings. 123 def setUp(self):
137 'down' : ROUND_DOWN, 124 self.context = self.decimal.Context()
138 'floor' : ROUND_FLOOR, 125 self.readcontext = self.decimal.Context()
139 'half_down' : ROUND_HALF_DOWN, 126 self.ignore_list = ['#']
140 'half_even' : ROUND_HALF_EVEN,
141 'half_up' : ROUND_HALF_UP,
142 'up' : ROUND_UP,
143 '05up' : ROUND_05UP}
144 127
145 # Name adapter to be able to change the Decimal and Context 128 # List of individual .decTest test ids that correspond to tests that
146 # interface without changing the test files from Cowlishaw 129 # we're skipping for one reason or another.
147 nameAdapter = {'and':'logical_and', 130 self.skipped_test_ids = set([
148 'apply':'_apply', 131 # Skip implementation-specific scaleb tests.
149 'class':'number_class', 132 'scbx164',
150 'comparesig':'compare_signal', 133 'scbx165',
151 'comparetotal':'compare_total',
152 'comparetotmag':'compare_total_mag',
153 'copy':'copy_decimal',
154 'copyabs':'copy_abs',
155 'copynegate':'copy_negate',
156 'copysign':'copy_sign',
157 'divideint':'divide_int',
158 'invert':'logical_invert',
159 'iscanonical':'is_canonical',
160 'isfinite':'is_finite',
161 'isinfinite':'is_infinite',
162 'isnan':'is_nan',
163 'isnormal':'is_normal',
164 'isqnan':'is_qnan',
165 'issigned':'is_signed',
166 'issnan':'is_snan',
167 'issubnormal':'is_subnormal',
168 'iszero':'is_zero',
169 'maxmag':'max_mag',
170 'minmag':'min_mag',
171 'nextminus':'next_minus',
172 'nextplus':'next_plus',
173 'nexttoward':'next_toward',
174 'or':'logical_or',
175 'reduce':'normalize',
176 'remaindernear':'remainder_near',
177 'samequantum':'same_quantum',
178 'squareroot':'sqrt',
179 'toeng':'to_eng_string',
180 'tointegral':'to_integral_value',
181 'tointegralx':'to_integral_exact',
182 'tosci':'to_sci_string',
183 'xor':'logical_xor',
184 }
185 134
186 # The following functions return True/False rather than a Decimal instance 135 # For some operations (currently exp, ln, log10, power), the decNumb er
136 # reference implementation imposes additional restrictions on the co ntext
137 # and operands. These restrictions are not part of the specificatio n;
138 # however, the effect of these restrictions does show up in some of the
139 # testcases. We skip testcases that violate these restrictions, sin ce
140 # Decimal behaves differently from decNumber for these testcases so these
141 # testcases would otherwise fail.
142 'expx901',
143 'expx902',
144 'expx903',
145 'expx905',
146 'lnx901',
147 'lnx902',
148 'lnx903',
149 'lnx905',
150 'logx901',
151 'logx902',
152 'logx903',
153 'logx905',
154 'powx1183',
155 'powx1184',
156 'powx4001',
157 'powx4002',
158 'powx4003',
159 'powx4005',
160 'powx4008',
161 'powx4010',
162 'powx4012',
163 'powx4014',
164 ])
187 165
188 LOGICAL_FUNCTIONS = ( 166 if self.decimal == C:
189 'is_canonical', 167 # status has additional Subnormal, Underflow
190 'is_finite', 168 self.skipped_test_ids.add('pwsx803')
191 'is_infinite', 169 self.skipped_test_ids.add('pwsx805')
192 'is_nan', 170 # Correct rounding (skipped for decNumber, too)
193 'is_normal', 171 self.skipped_test_ids.add('powx4302')
194 'is_qnan', 172 self.skipped_test_ids.add('powx4303')
195 'is_signed', 173 self.skipped_test_ids.add('powx4342')
196 'is_snan', 174 self.skipped_test_ids.add('powx4343')
197 'is_subnormal', 175 # http://bugs.python.org/issue7049
198 'is_zero', 176 self.skipped_test_ids.add('pwmx325')
199 'same_quantum', 177 self.skipped_test_ids.add('pwmx326')
200 )
201 178
202 class DecimalTest(unittest.TestCase): 179 # Map test directives to setter functions.
203 """Class which tests the Decimal class against the test cases. 180 self.ChangeDict = {'precision' : self.change_precision,
181 'rounding' : self.change_rounding_method,
182 'maxexponent' : self.change_max_exponent,
183 'minexponent' : self.change_min_exponent,
184 'clamp' : self.change_clamp}
204 185
205 Changed for unittest. 186 # Name adapter to be able to change the Decimal and Context
206 """ 187 # interface without changing the test files from Cowlishaw.
207 def setUp(self): 188 self.NameAdapter = {'and':'logical_and',
208 self.context = Context() 189 'apply':'_apply',
209 self.ignore_list = ['#'] 190 'class':'number_class',
210 # Basically, a # means return NaN InvalidOperation. 191 'comparesig':'compare_signal',
211 # Different from a sNaN in trim 192 'comparetotal':'compare_total',
193 'comparetotmag':'compare_total_mag',
194 'copy':'copy_decimal',
195 'copyabs':'copy_abs',
196 'copynegate':'copy_negate',
197 'copysign':'copy_sign',
198 'divideint':'divide_int',
199 'invert':'logical_invert',
200 'iscanonical':'is_canonical',
201 'isfinite':'is_finite',
202 'isinfinite':'is_infinite',
203 'isnan':'is_nan',
204 'isnormal':'is_normal',
205 'isqnan':'is_qnan',
206 'issigned':'is_signed',
207 'issnan':'is_snan',
208 'issubnormal':'is_subnormal',
209 'iszero':'is_zero',
210 'maxmag':'max_mag',
211 'minmag':'min_mag',
212 'nextminus':'next_minus',
213 'nextplus':'next_plus',
214 'nexttoward':'next_toward',
215 'or':'logical_or',
216 'reduce':'normalize',
217 'remaindernear':'remainder_near',
218 'samequantum':'same_quantum',
219 'squareroot':'sqrt',
220 'toeng':'to_eng_string',
221 'tointegral':'to_integral_value',
222 'tointegralx':'to_integral_exact',
223 'tosci':'to_sci_string',
224 'xor':'logical_xor'}
212 225
213 self.ChangeDict = {'precision' : self.change_precision, 226 # Map test-case names to roundings.
214 'rounding' : self.change_rounding_method, 227 self.RoundingDict = {'ceiling' : self.decimal.ROUND_CEILING,
215 'maxexponent' : self.change_max_exponent, 228 'down' : self.decimal.ROUND_DOWN,
216 'minexponent' : self.change_min_exponent, 229 'floor' : self.decimal.ROUND_FLOOR,
217 'clamp' : self.change_clamp} 230 'half_down' : self.decimal.ROUND_HALF_DOWN,
231 'half_even' : self.decimal.ROUND_HALF_EVEN,
232 'half_up' : self.decimal.ROUND_HALF_UP,
233 'up' : self.decimal.ROUND_UP,
234 '05up' : self.decimal.ROUND_05UP}
235
236 # Map the test cases' error names to the actual errors.
237 self.ErrorNames = {'clamped' : self.decimal.Clamped,
238 'conversion_syntax' : self.decimal.InvalidOperation,
239 'division_by_zero' : self.decimal.DivisionByZero,
240 'division_impossible' : self.decimal.InvalidOperation ,
241 'division_undefined' : self.decimal.InvalidOperation,
242 'inexact' : self.decimal.Inexact,
243 'invalid_context' : self.decimal.InvalidOperation,
244 'invalid_operation' : self.decimal.InvalidOperation,
245 'overflow' : self.decimal.Overflow,
246 'rounded' : self.decimal.Rounded,
247 'subnormal' : self.decimal.Subnormal,
248 'underflow' : self.decimal.Underflow}
249
250 # The following functions return True/False rather than a
251 # Decimal instance.
252 self.LogicalFunctions = ('is_canonical',
253 'is_finite',
254 'is_infinite',
255 'is_nan',
256 'is_normal',
257 'is_qnan',
258 'is_signed',
259 'is_snan',
260 'is_subnormal',
261 'is_zero',
262 'same_quantum')
263
264 def read_unlimited(self, v, context):
265 """Work around the limitations of the 32-bit _decimal version. The
266 guaranteed maximum values for prec, Emax etc. are 425000000,
267 but higher values usually work, except for rare corner cases.
268 In particular, all of the IBM tests pass with maximum values
269 of 1070000000."""
270 if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
271 self.readcontext._unsafe_setprec(1070000000)
272 self.readcontext._unsafe_setemax(1070000000)
273 self.readcontext._unsafe_setemin(-1070000000)
274 return self.readcontext.create_decimal(v)
275 else:
276 return self.decimal.Decimal(v, context)
218 277
219 def eval_file(self, file): 278 def eval_file(self, file):
220 global skip_expected 279 global skip_expected
221 if skip_expected: 280 if skip_expected:
222 raise unittest.SkipTest 281 raise unittest.SkipTest
223 return 282 return
224 with open(file) as f: 283 with open(file) as f:
225 for line in f: 284 for line in f:
226 line = line.replace('\r\n', '').replace('\n', '') 285 line = line.replace('\r\n', '').replace('\n', '')
227 #print line 286 #print line
228 try: 287 try:
229 t = self.eval_line(line) 288 t = self.eval_line(line)
230 except DecimalException as exception: 289 except self.decimal.DecimalException as exception:
231 #Exception raised where there shouldn't have been one. 290 #Exception raised where there shouldn't have been one.
232 self.fail('Exception "'+exception.__class__.__name__ + '" ra ised on line '+line) 291 self.fail('Exception "'+exception.__class__.__name__ + '" ra ised on line '+line)
233 292
234 return 293 return
235 294
236 def eval_line(self, s): 295 def eval_line(self, s):
237 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'): 296 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
238 s = (s.split('->')[0] + '->' + 297 s = (s.split('->')[0] + '->' +
239 s.split('->')[1].split('--')[0]).strip() 298 s.split('->')[1].split('--')[0]).strip()
240 else: 299 else:
241 s = s.split('--')[0].strip() 300 s = s.split('--')[0].strip()
242 301
243 for ignore in self.ignore_list: 302 for ignore in self.ignore_list:
244 if s.find(ignore) >= 0: 303 if s.find(ignore) >= 0:
245 #print s.split()[0], 'NotImplemented--', ignore 304 #print s.split()[0], 'NotImplemented--', ignore
246 return 305 return
247 if not s: 306 if not s:
248 return 307 return
249 elif ':' in s: 308 elif ':' in s:
250 return self.eval_directive(s) 309 return self.eval_directive(s)
251 else: 310 else:
252 return self.eval_equation(s) 311 return self.eval_equation(s)
253 312
254 def eval_directive(self, s): 313 def eval_directive(self, s):
255 funct, value = (x.strip().lower() for x in s.split(':')) 314 funct, value = (x.strip().lower() for x in s.split(':'))
256 if funct == 'rounding': 315 if funct == 'rounding':
257 value = RoundingDict[value] 316 value = self.RoundingDict[value]
258 else: 317 else:
259 try: 318 try:
260 value = int(value) 319 value = int(value)
261 except ValueError: 320 except ValueError:
262 pass 321 pass
263 322
264 funct = self.ChangeDict.get(funct, Nonfunction) 323 funct = self.ChangeDict.get(funct, (lambda *args: None))
265 funct(value) 324 funct(value)
266 325
267 def eval_equation(self, s): 326 def eval_equation(self, s):
268 #global DEFAULT_PRECISION
269 #print DEFAULT_PRECISION
270 327
271 if not TEST_ALL and random.random() < 0.90: 328 if not TEST_ALL and random.random() < 0.90:
272 return 329 return
273 330
331 self.context.clear_flags()
332
274 try: 333 try:
275 Sides = s.split('->') 334 Sides = s.split('->')
276 L = Sides[0].strip().split() 335 L = Sides[0].strip().split()
277 id = L[0] 336 id = L[0]
278 if DEBUG: 337 if DEBUG:
279 print("Test ", id, end=" ") 338 print("Test ", id, end=" ")
280 funct = L[1].lower() 339 funct = L[1].lower()
281 valstemp = L[2:] 340 valstemp = L[2:]
282 L = Sides[1].strip().split() 341 L = Sides[1].strip().split()
283 ans = L[0] 342 ans = L[0]
284 exceptions = L[1:] 343 exceptions = L[1:]
285 except (TypeError, AttributeError, IndexError): 344 except (TypeError, AttributeError, IndexError):
286 raise InvalidOperation 345 raise self.decimal.InvalidOperation
287 def FixQuotes(val): 346 def FixQuotes(val):
288 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote') 347 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
289 val = val.replace("'", '').replace('"', '') 348 val = val.replace("'", '').replace('"', '')
290 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"') 349 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
291 return val 350 return val
292 351
293 if id in skipped_test_ids: 352 if id in self.skipped_test_ids:
294 return 353 return
295 354
296 fname = nameAdapter.get(funct, funct) 355 fname = self.NameAdapter.get(funct, funct)
297 if fname == 'rescale': 356 if fname == 'rescale':
298 return 357 return
299 funct = getattr(self.context, fname) 358 funct = getattr(self.context, fname)
300 vals = [] 359 vals = []
301 conglomerate = '' 360 conglomerate = ''
302 quote = 0 361 quote = 0
303 theirexceptions = [ErrorNames[x.lower()] for x in exceptions] 362 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
304 363
305 for exception in Signals: 364 for exception in Signals[self.decimal]:
306 self.context.traps[exception] = 1 #Catch these bugs... 365 self.context.traps[exception] = 1 #Catch these bugs...
307 for exception in theirexceptions: 366 for exception in theirexceptions:
308 self.context.traps[exception] = 0 367 self.context.traps[exception] = 0
309 for i, val in enumerate(valstemp): 368 for i, val in enumerate(valstemp):
310 if val.count("'") % 2 == 1: 369 if val.count("'") % 2 == 1:
311 quote = 1 - quote 370 quote = 1 - quote
312 if quote: 371 if quote:
313 conglomerate = conglomerate + ' ' + val 372 conglomerate = conglomerate + ' ' + val
314 continue 373 continue
315 else: 374 else:
316 val = conglomerate + val 375 val = conglomerate + val
317 conglomerate = '' 376 conglomerate = ''
318 v = FixQuotes(val) 377 v = FixQuotes(val)
319 if fname in ('to_sci_string', 'to_eng_string'): 378 if fname in ('to_sci_string', 'to_eng_string'):
320 if EXTENDEDERRORTEST: 379 if EXTENDEDERRORTEST:
321 for error in theirexceptions: 380 for error in theirexceptions:
322 self.context.traps[error] = 1 381 self.context.traps[error] = 1
323 try: 382 try:
324 funct(self.context.create_decimal(v)) 383 funct(self.context.create_decimal(v))
325 except error: 384 except error:
326 pass 385 pass
327 except Signals as e: 386 except Signals[self.decimal] as e:
328 self.fail("Raised %s in %s when %s disabled" % \ 387 self.fail("Raised %s in %s when %s disabled" % \
329 (e, s, error)) 388 (e, s, error))
330 else: 389 else:
331 self.fail("Did not raise %s in %s" % (error, s)) 390 self.fail("Did not raise %s in %s" % (error, s))
332 self.context.traps[error] = 0 391 self.context.traps[error] = 0
333 v = self.context.create_decimal(v) 392 v = self.context.create_decimal(v)
334 else: 393 else:
335 v = Decimal(v, self.context) 394 v = self.read_unlimited(v, self.context)
336 vals.append(v) 395 vals.append(v)
337 396
338 ans = FixQuotes(ans) 397 ans = FixQuotes(ans)
339 398
340 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string') : 399 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string') :
341 for error in theirexceptions: 400 for error in theirexceptions:
342 self.context.traps[error] = 1 401 self.context.traps[error] = 1
343 try: 402 try:
344 funct(*vals) 403 funct(*vals)
345 except error: 404 except error:
346 pass 405 pass
347 except Signals as e: 406 except Signals[self.decimal] as e:
348 self.fail("Raised %s in %s when %s disabled" % \ 407 self.fail("Raised %s in %s when %s disabled" % \
349 (e, s, error)) 408 (e, s, error))
350 else: 409 else:
351 self.fail("Did not raise %s in %s" % (error, s)) 410 self.fail("Did not raise %s in %s" % (error, s))
352 self.context.traps[error] = 0 411 self.context.traps[error] = 0
353 412
354 # as above, but add traps cumulatively, to check precedence 413 # as above, but add traps cumulatively, to check precedence
355 ordered_errors = [e for e in OrderedSignals if e in theirexceptions] 414 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in th eirexceptions]
356 for error in ordered_errors: 415 for error in ordered_errors:
357 self.context.traps[error] = 1 416 self.context.traps[error] = 1
358 try: 417 try:
359 funct(*vals) 418 funct(*vals)
360 except error: 419 except error:
361 pass 420 pass
362 except Signals as e: 421 except Signals[self.decimal] as e:
363 self.fail("Raised %s in %s; expected %s" % 422 self.fail("Raised %s in %s; expected %s" %
364 (type(e), s, error)) 423 (type(e), s, error))
365 else: 424 else:
366 self.fail("Did not raise %s in %s" % (error, s)) 425 self.fail("Did not raise %s in %s" % (error, s))
367 # reset traps 426 # reset traps
368 for error in ordered_errors: 427 for error in ordered_errors:
369 self.context.traps[error] = 0 428 self.context.traps[error] = 0
370 429
371 430
372 if DEBUG: 431 if DEBUG:
373 print("--", self.context) 432 print("--", self.context)
374 try: 433 try:
375 result = str(funct(*vals)) 434 result = str(funct(*vals))
376 if fname in LOGICAL_FUNCTIONS: 435 if fname in self.LogicalFunctions:
377 result = str(int(eval(result))) # 'True', 'False' -> '1', '0' 436 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
378 except Signals as error: 437 except Signals[self.decimal] as error:
379 self.fail("Raised %s in %s" % (error, s)) 438 self.fail("Raised %s in %s" % (error, s))
380 except: #Catch any error long enough to state the test case. 439 except: #Catch any error long enough to state the test case.
381 print("ERROR:", s) 440 print("ERROR:", s)
382 raise 441 raise
383 442
384 myexceptions = self.getexceptions() 443 myexceptions = self.getexceptions()
385 self.context.clear_flags()
386 444
387 myexceptions.sort(key=repr) 445 myexceptions.sort(key=repr)
388 theirexceptions.sort(key=repr) 446 theirexceptions.sort(key=repr)
389 447
390 self.assertEqual(result, ans, 448 self.assertEqual(result, ans,
391 'Incorrect answer for ' + s + ' -- got ' + result) 449 'Incorrect answer for ' + s + ' -- got ' + result)
450
392 self.assertEqual(myexceptions, theirexceptions, 451 self.assertEqual(myexceptions, theirexceptions,
393 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions)) 452 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
394 return 453 return
395 454
396 def getexceptions(self): 455 def getexceptions(self):
397 return [e for e in Signals if self.context.flags[e]] 456 return [e for e in Signals[self.decimal] if self.context.flags[e]]
398 457
399 def change_precision(self, prec): 458 def change_precision(self, prec):
400 self.context.prec = prec 459 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
460 self.context._unsafe_setprec(prec)
461 else:
462 self.context.prec = prec
401 def change_rounding_method(self, rounding): 463 def change_rounding_method(self, rounding):
402 self.context.rounding = rounding 464 self.context.rounding = rounding
403 def change_min_exponent(self, exp): 465 def change_min_exponent(self, exp):
404 self.context.Emin = exp 466 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
467 self.context._unsafe_setemin(exp)
468 else:
469 self.context.Emin = exp
405 def change_max_exponent(self, exp): 470 def change_max_exponent(self, exp):
406 self.context.Emax = exp 471 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
472 self.context._unsafe_setemax(exp)
473 else:
474 self.context.Emax = exp
407 def change_clamp(self, clamp): 475 def change_clamp(self, clamp):
408 self.context.clamp = clamp 476 self.context.clamp = clamp
409 477
410 478 class CIBMTestCases(IBMTestCases):
479 decimal = C
480 class PyIBMTestCases(IBMTestCases):
481 decimal = P
411 482
412 # The following classes test the behaviour of Decimal according to PEP 327 483 # The following classes test the behaviour of Decimal according to PEP 327
413 484
414 class DecimalExplicitConstructionTest(unittest.TestCase): 485 class ExplicitConstructionTest(unittest.TestCase):
415 '''Unit tests for Explicit Construction cases of Decimal.''' 486 '''Unit tests for Explicit Construction cases of Decimal.'''
416 487
417 def test_explicit_empty(self): 488 def test_explicit_empty(self):
489 Decimal = self.decimal.Decimal
418 self.assertEqual(Decimal(), Decimal("0")) 490 self.assertEqual(Decimal(), Decimal("0"))
419 491
420 def test_explicit_from_None(self): 492 def test_explicit_from_None(self):
493 Decimal = self.decimal.Decimal
421 self.assertRaises(TypeError, Decimal, None) 494 self.assertRaises(TypeError, Decimal, None)
422 495
423 def test_explicit_from_int(self): 496 def test_explicit_from_int(self):
497 Decimal = self.decimal.Decimal
424 498
425 #positive 499 #positive
426 d = Decimal(45) 500 d = Decimal(45)
427 self.assertEqual(str(d), '45') 501 self.assertEqual(str(d), '45')
428 502
429 #very large positive 503 #very large positive
430 d = Decimal(500000123) 504 d = Decimal(500000123)
431 self.assertEqual(str(d), '500000123') 505 self.assertEqual(str(d), '500000123')
432 506
433 #negative 507 #negative
434 d = Decimal(-45) 508 d = Decimal(-45)
435 self.assertEqual(str(d), '-45') 509 self.assertEqual(str(d), '-45')
436 510
437 #zero 511 #zero
438 d = Decimal(0) 512 d = Decimal(0)
439 self.assertEqual(str(d), '0') 513 self.assertEqual(str(d), '0')
440 514
515 # single word longs
516 for n in range(0, 32):
517 for sign in (-1, 1):
518 for x in range(-5, 5):
519 i = sign * (2**n + x)
520 d = Decimal(i)
521 self.assertEqual(str(d), str(i))
522
441 def test_explicit_from_string(self): 523 def test_explicit_from_string(self):
524 Decimal = self.decimal.Decimal
525 InvalidOperation = self.decimal.InvalidOperation
526 localcontext = self.decimal.localcontext
442 527
443 #empty 528 #empty
444 self.assertEqual(str(Decimal('')), 'NaN') 529 self.assertEqual(str(Decimal('')), 'NaN')
445 530
446 #int 531 #int
447 self.assertEqual(str(Decimal('45')), '45') 532 self.assertEqual(str(Decimal('45')), '45')
448 533
449 #float 534 #float
450 self.assertEqual(str(Decimal('45.34')), '45.34') 535 self.assertEqual(str(Decimal('45.34')), '45.34')
451 536
452 #engineer notation 537 #engineer notation
453 self.assertEqual(str(Decimal('45e2')), '4.5E+3') 538 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
454 539
455 #just not a number 540 #just not a number
456 self.assertEqual(str(Decimal('ugly')), 'NaN') 541 self.assertEqual(str(Decimal('ugly')), 'NaN')
457 542
458 #leading and trailing whitespace permitted 543 #leading and trailing whitespace permitted
459 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4') 544 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
460 self.assertEqual(str(Decimal(' -7.89')), '-7.89') 545 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
546 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
547
548 # unicode whitespace
549 for lead in ["", ' ', '\u00a0', '\u205f']:
550 for trail in ["", ' ', '\u00a0', '\u205f']:
551 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
552 '9.311E+28')
553
554 with localcontext() as c:
555 c.traps[InvalidOperation] = True
556 # Invalid string
557 self.assertRaises(InvalidOperation, Decimal, "xyz")
558 # Two arguments max
559 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
560
561 # space within the numeric part
562 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
563 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
564
565 # unicode whitespace
566 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
567 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
568
569 # embedded NUL
570 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
571
461 572
462 def test_explicit_from_tuples(self): 573 def test_explicit_from_tuples(self):
574 Decimal = self.decimal.Decimal
463 575
464 #zero 576 #zero
465 d = Decimal( (0, (0,), 0) ) 577 d = Decimal( (0, (0,), 0) )
466 self.assertEqual(str(d), '0') 578 self.assertEqual(str(d), '0')
467 579
468 #int 580 #int
469 d = Decimal( (1, (4, 5), 0) ) 581 d = Decimal( (1, (4, 5), 0) )
470 self.assertEqual(str(d), '-45') 582 self.assertEqual(str(d), '-45')
471 583
472 #float 584 #float
473 d = Decimal( (0, (4, 5, 3, 4), -2) ) 585 d = Decimal( (0, (4, 5, 3, 4), -2) )
474 self.assertEqual(str(d), '45.34') 586 self.assertEqual(str(d), '45.34')
475 587
476 #weird 588 #weird
477 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) ) 589 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
478 self.assertEqual(str(d), '-4.34913534E-17') 590 self.assertEqual(str(d), '-4.34913534E-17')
591
592 #inf
593 d = Decimal( (0, (), "F") )
594 self.assertEqual(str(d), 'Infinity')
479 595
480 #wrong number of items 596 #wrong number of items
481 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) ) 597 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
482 598
483 #bad sign 599 #bad sign
484 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) ) 600 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
485 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) ) 601 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
486 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2)) 602 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
487 603
488 #bad exp 604 #bad exp
489 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') ) 605 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
490 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) ) 606 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
491 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') ) 607 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
492 608
493 #bad coefficients 609 #bad coefficients
610 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
494 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) ) 611 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
495 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) ) 612 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
496 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) ) 613 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
497 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) ) 614 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
498 615
616 def test_explicit_from_list(self):
617 Decimal = self.decimal.Decimal
618
619 d = Decimal([0, [0], 0])
620 self.assertEqual(str(d), '0')
621
622 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
623 self.assertEqual(str(d), '-4.34913534E-17')
624
625 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
626 self.assertEqual(str(d), '-4.34913534E-17')
627
628 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
629 self.assertEqual(str(d), '-4.34913534E-17')
630
499 def test_explicit_from_bool(self): 631 def test_explicit_from_bool(self):
632 Decimal = self.decimal.Decimal
633
500 self.assertIs(bool(Decimal(0)), False) 634 self.assertIs(bool(Decimal(0)), False)
501 self.assertIs(bool(Decimal(1)), True) 635 self.assertIs(bool(Decimal(1)), True)
502 self.assertEqual(Decimal(False), Decimal(0)) 636 self.assertEqual(Decimal(False), Decimal(0))
503 self.assertEqual(Decimal(True), Decimal(1)) 637 self.assertEqual(Decimal(True), Decimal(1))
504 638
505 def test_explicit_from_Decimal(self): 639 def test_explicit_from_Decimal(self):
640 Decimal = self.decimal.Decimal
506 641
507 #positive 642 #positive
508 d = Decimal(45) 643 d = Decimal(45)
509 e = Decimal(d) 644 e = Decimal(d)
510 self.assertEqual(str(e), '45') 645 self.assertEqual(str(e), '45')
511 self.assertNotEqual(id(d), id(e))
512 646
513 #very large positive 647 #very large positive
514 d = Decimal(500000123) 648 d = Decimal(500000123)
515 e = Decimal(d) 649 e = Decimal(d)
516 self.assertEqual(str(e), '500000123') 650 self.assertEqual(str(e), '500000123')
517 self.assertNotEqual(id(d), id(e))
518 651
519 #negative 652 #negative
520 d = Decimal(-45) 653 d = Decimal(-45)
521 e = Decimal(d) 654 e = Decimal(d)
522 self.assertEqual(str(e), '-45') 655 self.assertEqual(str(e), '-45')
523 self.assertNotEqual(id(d), id(e))
524 656
525 #zero 657 #zero
526 d = Decimal(0) 658 d = Decimal(0)
527 e = Decimal(d) 659 e = Decimal(d)
528 self.assertEqual(str(e), '0') 660 self.assertEqual(str(e), '0')
529 self.assertNotEqual(id(d), id(e))
530 661
531 @requires_IEEE_754 662 @requires_IEEE_754
532 def test_explicit_from_float(self): 663 def test_explicit_from_float(self):
664
665 Decimal = self.decimal.Decimal
666
533 r = Decimal(0.1) 667 r = Decimal(0.1)
534 self.assertEqual(type(r), Decimal) 668 self.assertEqual(type(r), Decimal)
535 self.assertEqual(str(r), 669 self.assertEqual(str(r),
536 '0.1000000000000000055511151231257827021181583404541015625') 670 '0.1000000000000000055511151231257827021181583404541015625')
537 self.assertTrue(Decimal(float('nan')).is_qnan()) 671 self.assertTrue(Decimal(float('nan')).is_qnan())
538 self.assertTrue(Decimal(float('inf')).is_infinite()) 672 self.assertTrue(Decimal(float('inf')).is_infinite())
539 self.assertTrue(Decimal(float('-inf')).is_infinite()) 673 self.assertTrue(Decimal(float('-inf')).is_infinite())
540 self.assertEqual(str(Decimal(float('nan'))), 674 self.assertEqual(str(Decimal(float('nan'))),
541 str(Decimal('NaN'))) 675 str(Decimal('NaN')))
542 self.assertEqual(str(Decimal(float('inf'))), 676 self.assertEqual(str(Decimal(float('inf'))),
543 str(Decimal('Infinity'))) 677 str(Decimal('Infinity')))
544 self.assertEqual(str(Decimal(float('-inf'))), 678 self.assertEqual(str(Decimal(float('-inf'))),
545 str(Decimal('-Infinity'))) 679 str(Decimal('-Infinity')))
546 self.assertEqual(str(Decimal(float('-0.0'))), 680 self.assertEqual(str(Decimal(float('-0.0'))),
547 str(Decimal('-0'))) 681 str(Decimal('-0')))
548 for i in range(200): 682 for i in range(200):
549 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0) 683 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
550 self.assertEqual(x, float(Decimal(x))) # roundtrip 684 self.assertEqual(x, float(Decimal(x))) # roundtrip
551 685
552 def test_explicit_context_create_decimal(self): 686 def test_explicit_context_create_decimal(self):
687 Decimal = self.decimal.Decimal
688 InvalidOperation = self.decimal.InvalidOperation
689 Rounded = self.decimal.Rounded
553 690
554 nc = copy.copy(getcontext()) 691 nc = copy.copy(self.decimal.getcontext())
555 nc.prec = 3 692 nc.prec = 3
556 693
557 # empty 694 # empty
558 d = Decimal() 695 d = Decimal()
559 self.assertEqual(str(d), '0') 696 self.assertEqual(str(d), '0')
560 d = nc.create_decimal() 697 d = nc.create_decimal()
561 self.assertEqual(str(d), '0') 698 self.assertEqual(str(d), '0')
562 699
563 # from None 700 # from None
564 self.assertRaises(TypeError, nc.create_decimal, None) 701 self.assertRaises(TypeError, nc.create_decimal, None)
(...skipping 20 matching lines...) Expand all
585 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) ) 722 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
586 self.assertEqual(str(d), '-4.35E-17') 723 self.assertEqual(str(d), '-4.35E-17')
587 724
588 # from Decimal 725 # from Decimal
589 prevdec = Decimal(500000123) 726 prevdec = Decimal(500000123)
590 d = Decimal(prevdec) 727 d = Decimal(prevdec)
591 self.assertEqual(str(d), '500000123') 728 self.assertEqual(str(d), '500000123')
592 d = nc.create_decimal(prevdec) 729 d = nc.create_decimal(prevdec)
593 self.assertEqual(str(d), '5.00E+8') 730 self.assertEqual(str(d), '5.00E+8')
594 731
732 # more integers
733 nc.prec = 28
734 nc.traps[InvalidOperation] = True
735
736 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
737 2**31-1, 2**31, 2**63-1, 2**63]:
738 d = nc.create_decimal(v)
739 self.assertTrue(isinstance(d, Decimal))
740 self.assertEqual(int(d), v)
741
742 nc.prec = 3
743 nc.traps[Rounded] = True
744 self.assertRaises(Rounded, nc.create_decimal, 1234)
745
746 # from string
747 nc.prec = 28
748 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
749 self.assertEqual(str(nc.create_decimal('45')), '45')
750 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
751 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
752
753 # invalid arguments
754 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
755 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
756 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
757
758 # too many NaN payload digits
759 nc.prec = 3
760 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
761 self.assertRaises(InvalidOperation, nc.create_decimal,
762 Decimal('NaN12345'))
763
764 nc.traps[InvalidOperation] = False
765 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
766 self.assertTrue(nc.flags[InvalidOperation])
767
768 nc.flags[InvalidOperation] = False
769 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
770 self.assertTrue(nc.flags[InvalidOperation])
771
772 def test_explicit_context_create_from_float(self):
773
774 Decimal = self.decimal.Decimal
775
776 nc = self.decimal.Context()
777 r = nc.create_decimal(0.1)
778 self.assertEqual(type(r), Decimal)
779 self.assertEqual(str(r), '0.1000000000000000055511151231')
780 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
781 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
782 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
783 self.assertEqual(str(nc.create_decimal(float('nan'))),
784 str(nc.create_decimal('NaN')))
785 self.assertEqual(str(nc.create_decimal(float('inf'))),
786 str(nc.create_decimal('Infinity')))
787 self.assertEqual(str(nc.create_decimal(float('-inf'))),
788 str(nc.create_decimal('-Infinity')))
789 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
790 str(nc.create_decimal('-0')))
791 nc.prec = 100
792 for i in range(200):
793 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
794 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
795
595 def test_unicode_digits(self): 796 def test_unicode_digits(self):
797 Decimal = self.decimal.Decimal
798
596 test_values = { 799 test_values = {
597 '\uff11': '1', 800 '\uff11': '1',
598 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372', 801 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
599 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400', 802 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
600 } 803 }
601 for input, expected in test_values.items(): 804 for input, expected in test_values.items():
602 self.assertEqual(str(Decimal(input)), expected) 805 self.assertEqual(str(Decimal(input)), expected)
603 806
807 class CExplicitConstructionTest(ExplicitConstructionTest):
808 decimal = C
809 class PyExplicitConstructionTest(ExplicitConstructionTest):
810 decimal = P
604 811
605 class DecimalImplicitConstructionTest(unittest.TestCase): 812 class ImplicitConstructionTest(unittest.TestCase):
606 '''Unit tests for Implicit Construction cases of Decimal.''' 813 '''Unit tests for Implicit Construction cases of Decimal.'''
607 814
608 def test_implicit_from_None(self): 815 def test_implicit_from_None(self):
609 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals()) 816 Decimal = self.decimal.Decimal
817 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
610 818
611 def test_implicit_from_int(self): 819 def test_implicit_from_int(self):
820 Decimal = self.decimal.Decimal
821
612 #normal 822 #normal
613 self.assertEqual(str(Decimal(5) + 45), '50') 823 self.assertEqual(str(Decimal(5) + 45), '50')
614 #exceeding precision 824 #exceeding precision
615 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000)) 825 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
616 826
617 def test_implicit_from_string(self): 827 def test_implicit_from_string(self):
618 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals()) 828 Decimal = self.decimal.Decimal
829 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
619 830
620 def test_implicit_from_float(self): 831 def test_implicit_from_float(self):
621 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals()) 832 Decimal = self.decimal.Decimal
833 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
622 834
623 def test_implicit_from_Decimal(self): 835 def test_implicit_from_Decimal(self):
836 Decimal = self.decimal.Decimal
624 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50)) 837 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
625 838
626 def test_rop(self): 839 def test_rop(self):
840 Decimal = self.decimal.Decimal
841
627 # Allow other classes to be trained to interact with Decimals 842 # Allow other classes to be trained to interact with Decimals
628 class E: 843 class E:
629 def __divmod__(self, other): 844 def __divmod__(self, other):
630 return 'divmod ' + str(other) 845 return 'divmod ' + str(other)
631 def __rdivmod__(self, other): 846 def __rdivmod__(self, other):
632 return str(other) + ' rdivmod' 847 return str(other) + ' rdivmod'
633 def __lt__(self, other): 848 def __lt__(self, other):
634 return 'lt ' + str(other) 849 return 'lt ' + str(other)
635 def __gt__(self, other): 850 def __gt__(self, other):
636 return 'gt ' + str(other) 851 return 'gt ' + str(other)
(...skipping 27 matching lines...) Expand all
664 ] 879 ]
665 880
666 for sym, lop, rop in oplist: 881 for sym, lop, rop in oplist:
667 setattr(E, lop, lambda self, other: 'str' + lop + str(other)) 882 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
668 setattr(E, rop, lambda self, other: str(other) + rop + 'str') 883 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
669 self.assertEqual(eval('E()' + sym + 'Decimal(10)'), 884 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
670 'str' + lop + '10') 885 'str' + lop + '10')
671 self.assertEqual(eval('Decimal(10)' + sym + 'E()'), 886 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
672 '10' + rop + 'str') 887 '10' + rop + 'str')
673 888
889 class CImplicitConstructionTest(ImplicitConstructionTest):
890 decimal = C
891 class PyImplicitConstructionTest(ImplicitConstructionTest):
892 decimal = P
674 893
675 class DecimalFormatTest(unittest.TestCase): 894 class FormatTest(unittest.TestCase):
676 '''Unit tests for the format function.''' 895 '''Unit tests for the format function.'''
677 def test_formatting(self): 896 def test_formatting(self):
897 Decimal = self.decimal.Decimal
898
678 # triples giving a format, a Decimal, and the expected result 899 # triples giving a format, a Decimal, and the expected result
679 test_values = [ 900 test_values = [
680 ('e', '0E-15', '0e-15'), 901 ('e', '0E-15', '0e-15'),
681 ('e', '2.3E-15', '2.3e-15'), 902 ('e', '2.3E-15', '2.3e-15'),
682 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros 903 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
683 ('e', '2.30000E-15', '2.30000e-15'), 904 ('e', '2.30000E-15', '2.30000e-15'),
684 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'), 905 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
685 ('e', '1.5', '1.5e+0'), 906 ('e', '1.5', '1.5e+0'),
686 ('e', '0.15', '1.5e-1'), 907 ('e', '0.15', '1.5e-1'),
687 ('e', '0.015', '1.5e-2'), 908 ('e', '0.015', '1.5e-2'),
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 944
724 ('g', '0', '0'), 945 ('g', '0', '0'),
725 ('g', '0.0', '0.0'), 946 ('g', '0.0', '0.0'),
726 ('g', '0E1', '0e+1'), 947 ('g', '0E1', '0e+1'),
727 ('G', '0E1', '0E+1'), 948 ('G', '0E1', '0E+1'),
728 ('g', '0E-5', '0.00000'), 949 ('g', '0E-5', '0.00000'),
729 ('g', '0E-6', '0.000000'), 950 ('g', '0E-6', '0.000000'),
730 ('g', '0E-7', '0e-7'), 951 ('g', '0E-7', '0e-7'),
731 ('g', '-0E2', '-0e+2'), 952 ('g', '-0E2', '-0e+2'),
732 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig 953 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
954 ('.0n', '3.14159265', '3'), # same for 'n'
733 ('.1g', '3.14159265', '3'), 955 ('.1g', '3.14159265', '3'),
734 ('.2g', '3.14159265', '3.1'), 956 ('.2g', '3.14159265', '3.1'),
735 ('.5g', '3.14159265', '3.1416'), 957 ('.5g', '3.14159265', '3.1416'),
736 ('.7g', '3.14159265', '3.141593'), 958 ('.7g', '3.14159265', '3.141593'),
737 ('.8g', '3.14159265', '3.1415926'), # round-half-even! 959 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
738 ('.9g', '3.14159265', '3.14159265'), 960 ('.9g', '3.14159265', '3.14159265'),
739 ('.10g', '3.14159265', '3.14159265'), # don't pad 961 ('.10g', '3.14159265', '3.14159265'), # don't pad
740 962
741 ('%', '0E1', '0%'), 963 ('%', '0E1', '0%'),
742 ('%', '0E0', '0%'), 964 ('%', '0E0', '0%'),
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 ('012,', '1234.56', '0,001,234.56'), 1029 ('012,', '1234.56', '0,001,234.56'),
808 ('08,.1f', '1234.5', '01,234.5'), 1030 ('08,.1f', '1234.5', '01,234.5'),
809 # no thousands separators in fraction part 1031 # no thousands separators in fraction part
810 (',', '1.23456789', '1.23456789'), 1032 (',', '1.23456789', '1.23456789'),
811 (',%', '123.456789', '12,345.6789%'), 1033 (',%', '123.456789', '12,345.6789%'),
812 (',e', '123456', '1.23456e+5'), 1034 (',e', '123456', '1.23456e+5'),
813 (',E', '123456', '1.23456E+5'), 1035 (',E', '123456', '1.23456E+5'),
814 1036
815 # issue 6850 1037 # issue 6850
816 ('a=-7.0', '0.12345', 'aaaa0.1'), 1038 ('a=-7.0', '0.12345', 'aaaa0.1'),
817
818 # Issue 7094: Alternate formatting (specified by #)
819 ('.0e', '1.0', '1e+0'),
820 ('#.0e', '1.0', '1.e+0'),
821 ('.0f', '1.0', '1'),
822 ('#.0f', '1.0', '1.'),
823 ('g', '1.1', '1.1'),
824 ('#g', '1.1', '1.1'),
825 ('.0g', '1', '1'),
826 ('#.0g', '1', '1.'),
827 ('.0%', '1.0', '100%'),
828 ('#.0%', '1.0', '100.%'),
829 ] 1039 ]
830 for fmt, d, result in test_values: 1040 for fmt, d, result in test_values:
831 self.assertEqual(format(Decimal(d), fmt), result) 1041 self.assertEqual(format(Decimal(d), fmt), result)
832 1042
1043 # bytes format argument
1044 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1045
833 def test_n_format(self): 1046 def test_n_format(self):
1047 Decimal = self.decimal.Decimal
1048
834 try: 1049 try:
835 from locale import CHAR_MAX 1050 from locale import CHAR_MAX
836 except ImportError: 1051 except ImportError:
837 return 1052 return
838 1053
1054 def make_grouping(lst):
1055 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1056
1057 def get_fmt(x, override=None, fmt='n'):
1058 if self.decimal == C:
1059 return Decimal(x).__format__(fmt, override)
1060 else:
1061 return Decimal(x).__format__(fmt, _localeconv=override)
1062
839 # Set up some localeconv-like dictionaries 1063 # Set up some localeconv-like dictionaries
840 en_US = { 1064 en_US = {
841 'decimal_point' : '.', 1065 'decimal_point' : '.',
842 'grouping' : [3, 3, 0], 1066 'grouping' : make_grouping([3, 3, 0]),
843 'thousands_sep': ',' 1067 'thousands_sep' : ','
844 } 1068 }
845 1069
846 fr_FR = { 1070 fr_FR = {
847 'decimal_point' : ',', 1071 'decimal_point' : ',',
848 'grouping' : [CHAR_MAX], 1072 'grouping' : make_grouping([CHAR_MAX]),
849 'thousands_sep' : '' 1073 'thousands_sep' : ''
850 } 1074 }
851 1075
852 ru_RU = { 1076 ru_RU = {
853 'decimal_point' : ',', 1077 'decimal_point' : ',',
854 'grouping' : [3, 3, 0], 1078 'grouping': make_grouping([3, 3, 0]),
855 'thousands_sep' : ' ' 1079 'thousands_sep' : ' '
856 } 1080 }
857 1081
858 crazy = { 1082 crazy = {
859 'decimal_point' : '&', 1083 'decimal_point' : '&',
860 'grouping' : [1, 4, 2, CHAR_MAX], 1084 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
861 'thousands_sep' : '-' 1085 'thousands_sep' : '-'
862 } 1086 }
863 1087
864 1088 dotsep_wide = {
865 def get_fmt(x, locale, fmt='n'): 1089 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
866 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale) 1090 'grouping': make_grouping([3, 3, 0]),
1091 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1092 }
867 1093
868 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7') 1094 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
869 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7') 1095 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
870 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7') 1096 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
871 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7') 1097 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
872 1098
873 self.assertEqual(get_fmt(123456789, en_US), '123,456,789') 1099 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
874 self.assertEqual(get_fmt(123456789, fr_FR), '123456789') 1100 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
875 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789') 1101 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
876 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3') 1102 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
(...skipping 18 matching lines...) Expand all
895 1121
896 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6') 1122 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
897 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6') 1123 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
898 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6') 1124 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
899 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6') 1125 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
900 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6') 1126 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
901 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6') 1127 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
902 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6') 1128 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
903 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6') 1129 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
904 1130
1131 # wide char separator and decimal point
1132 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1133 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
905 1134
906 class DecimalArithmeticOperatorsTest(unittest.TestCase): 1135 def test_wide_char_separator_decimal_point(self):
1136 # locale with wide char separator and decimal point
1137 Decimal = self.decimal.Decimal
1138
1139 try:
1140 locale.setlocale(locale.LC_ALL, 'ps_AF')
1141 except locale.Error:
1142 return
1143
1144 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1145 '100\u066c000\u066c000\u066b123')
1146 locale.resetlocale()
1147
1148 class CFormatTest(FormatTest):
1149 decimal = C
1150 class PyFormatTest(FormatTest):
1151 decimal = P
1152
1153 class ArithmeticOperatorsTest(unittest.TestCase):
907 '''Unit tests for all arithmetic operators, binary and unary.''' 1154 '''Unit tests for all arithmetic operators, binary and unary.'''
908 1155
909 def test_addition(self): 1156 def test_addition(self):
1157 Decimal = self.decimal.Decimal
910 1158
911 d1 = Decimal('-11.1') 1159 d1 = Decimal('-11.1')
912 d2 = Decimal('22.2') 1160 d2 = Decimal('22.2')
913 1161
914 #two Decimals 1162 #two Decimals
915 self.assertEqual(d1+d2, Decimal('11.1')) 1163 self.assertEqual(d1+d2, Decimal('11.1'))
916 self.assertEqual(d2+d1, Decimal('11.1')) 1164 self.assertEqual(d2+d1, Decimal('11.1'))
917 1165
918 #with other type, left 1166 #with other type, left
919 c = d1 + 5 1167 c = d1 + 5
920 self.assertEqual(c, Decimal('-6.1')) 1168 self.assertEqual(c, Decimal('-6.1'))
921 self.assertEqual(type(c), type(d1)) 1169 self.assertEqual(type(c), type(d1))
922 1170
923 #with other type, right 1171 #with other type, right
924 c = 5 + d1 1172 c = 5 + d1
925 self.assertEqual(c, Decimal('-6.1')) 1173 self.assertEqual(c, Decimal('-6.1'))
926 self.assertEqual(type(c), type(d1)) 1174 self.assertEqual(type(c), type(d1))
927 1175
928 #inline with decimal 1176 #inline with decimal
929 d1 += d2 1177 d1 += d2
930 self.assertEqual(d1, Decimal('11.1')) 1178 self.assertEqual(d1, Decimal('11.1'))
931 1179
932 #inline with other type 1180 #inline with other type
933 d1 += 5 1181 d1 += 5
934 self.assertEqual(d1, Decimal('16.1')) 1182 self.assertEqual(d1, Decimal('16.1'))
935 1183
936 def test_subtraction(self): 1184 def test_subtraction(self):
1185 Decimal = self.decimal.Decimal
937 1186
938 d1 = Decimal('-11.1') 1187 d1 = Decimal('-11.1')
939 d2 = Decimal('22.2') 1188 d2 = Decimal('22.2')
940 1189
941 #two Decimals 1190 #two Decimals
942 self.assertEqual(d1-d2, Decimal('-33.3')) 1191 self.assertEqual(d1-d2, Decimal('-33.3'))
943 self.assertEqual(d2-d1, Decimal('33.3')) 1192 self.assertEqual(d2-d1, Decimal('33.3'))
944 1193
945 #with other type, left 1194 #with other type, left
946 c = d1 - 5 1195 c = d1 - 5
947 self.assertEqual(c, Decimal('-16.1')) 1196 self.assertEqual(c, Decimal('-16.1'))
948 self.assertEqual(type(c), type(d1)) 1197 self.assertEqual(type(c), type(d1))
949 1198
950 #with other type, right 1199 #with other type, right
951 c = 5 - d1 1200 c = 5 - d1
952 self.assertEqual(c, Decimal('16.1')) 1201 self.assertEqual(c, Decimal('16.1'))
953 self.assertEqual(type(c), type(d1)) 1202 self.assertEqual(type(c), type(d1))
954 1203
955 #inline with decimal 1204 #inline with decimal
956 d1 -= d2 1205 d1 -= d2
957 self.assertEqual(d1, Decimal('-33.3')) 1206 self.assertEqual(d1, Decimal('-33.3'))
958 1207
959 #inline with other type 1208 #inline with other type
960 d1 -= 5 1209 d1 -= 5
961 self.assertEqual(d1, Decimal('-38.3')) 1210 self.assertEqual(d1, Decimal('-38.3'))
962 1211
963 def test_multiplication(self): 1212 def test_multiplication(self):
1213 Decimal = self.decimal.Decimal
964 1214
965 d1 = Decimal('-5') 1215 d1 = Decimal('-5')
966 d2 = Decimal('3') 1216 d2 = Decimal('3')
967 1217
968 #two Decimals 1218 #two Decimals
969 self.assertEqual(d1*d2, Decimal('-15')) 1219 self.assertEqual(d1*d2, Decimal('-15'))
970 self.assertEqual(d2*d1, Decimal('-15')) 1220 self.assertEqual(d2*d1, Decimal('-15'))
971 1221
972 #with other type, left 1222 #with other type, left
973 c = d1 * 5 1223 c = d1 * 5
974 self.assertEqual(c, Decimal('-25')) 1224 self.assertEqual(c, Decimal('-25'))
975 self.assertEqual(type(c), type(d1)) 1225 self.assertEqual(type(c), type(d1))
976 1226
977 #with other type, right 1227 #with other type, right
978 c = 5 * d1 1228 c = 5 * d1
979 self.assertEqual(c, Decimal('-25')) 1229 self.assertEqual(c, Decimal('-25'))
980 self.assertEqual(type(c), type(d1)) 1230 self.assertEqual(type(c), type(d1))
981 1231
982 #inline with decimal 1232 #inline with decimal
983 d1 *= d2 1233 d1 *= d2
984 self.assertEqual(d1, Decimal('-15')) 1234 self.assertEqual(d1, Decimal('-15'))
985 1235
986 #inline with other type 1236 #inline with other type
987 d1 *= 5 1237 d1 *= 5
988 self.assertEqual(d1, Decimal('-75')) 1238 self.assertEqual(d1, Decimal('-75'))
989 1239
990 def test_division(self): 1240 def test_division(self):
1241 Decimal = self.decimal.Decimal
991 1242
992 d1 = Decimal('-5') 1243 d1 = Decimal('-5')
993 d2 = Decimal('2') 1244 d2 = Decimal('2')
994 1245
995 #two Decimals 1246 #two Decimals
996 self.assertEqual(d1/d2, Decimal('-2.5')) 1247 self.assertEqual(d1/d2, Decimal('-2.5'))
997 self.assertEqual(d2/d1, Decimal('-0.4')) 1248 self.assertEqual(d2/d1, Decimal('-0.4'))
998 1249
999 #with other type, left 1250 #with other type, left
1000 c = d1 / 4 1251 c = d1 / 4
1001 self.assertEqual(c, Decimal('-1.25')) 1252 self.assertEqual(c, Decimal('-1.25'))
1002 self.assertEqual(type(c), type(d1)) 1253 self.assertEqual(type(c), type(d1))
1003 1254
1004 #with other type, right 1255 #with other type, right
1005 c = 4 / d1 1256 c = 4 / d1
1006 self.assertEqual(c, Decimal('-0.8')) 1257 self.assertEqual(c, Decimal('-0.8'))
1007 self.assertEqual(type(c), type(d1)) 1258 self.assertEqual(type(c), type(d1))
1008 1259
1009 #inline with decimal 1260 #inline with decimal
1010 d1 /= d2 1261 d1 /= d2
1011 self.assertEqual(d1, Decimal('-2.5')) 1262 self.assertEqual(d1, Decimal('-2.5'))
1012 1263
1013 #inline with other type 1264 #inline with other type
1014 d1 /= 4 1265 d1 /= 4
1015 self.assertEqual(d1, Decimal('-0.625')) 1266 self.assertEqual(d1, Decimal('-0.625'))
1016 1267
1017 def test_floor_division(self): 1268 def test_floor_division(self):
1269 Decimal = self.decimal.Decimal
1018 1270
1019 d1 = Decimal('5') 1271 d1 = Decimal('5')
1020 d2 = Decimal('2') 1272 d2 = Decimal('2')
1021 1273
1022 #two Decimals 1274 #two Decimals
1023 self.assertEqual(d1//d2, Decimal('2')) 1275 self.assertEqual(d1//d2, Decimal('2'))
1024 self.assertEqual(d2//d1, Decimal('0')) 1276 self.assertEqual(d2//d1, Decimal('0'))
1025 1277
1026 #with other type, left 1278 #with other type, left
1027 c = d1 // 4 1279 c = d1 // 4
1028 self.assertEqual(c, Decimal('1')) 1280 self.assertEqual(c, Decimal('1'))
1029 self.assertEqual(type(c), type(d1)) 1281 self.assertEqual(type(c), type(d1))
1030 1282
1031 #with other type, right 1283 #with other type, right
1032 c = 7 // d1 1284 c = 7 // d1
1033 self.assertEqual(c, Decimal('1')) 1285 self.assertEqual(c, Decimal('1'))
1034 self.assertEqual(type(c), type(d1)) 1286 self.assertEqual(type(c), type(d1))
1035 1287
1036 #inline with decimal 1288 #inline with decimal
1037 d1 //= d2 1289 d1 //= d2
1038 self.assertEqual(d1, Decimal('2')) 1290 self.assertEqual(d1, Decimal('2'))
1039 1291
1040 #inline with other type 1292 #inline with other type
1041 d1 //= 2 1293 d1 //= 2
1042 self.assertEqual(d1, Decimal('1')) 1294 self.assertEqual(d1, Decimal('1'))
1043 1295
1044 def test_powering(self): 1296 def test_powering(self):
1297 Decimal = self.decimal.Decimal
1045 1298
1046 d1 = Decimal('5') 1299 d1 = Decimal('5')
1047 d2 = Decimal('2') 1300 d2 = Decimal('2')
1048 1301
1049 #two Decimals 1302 #two Decimals
1050 self.assertEqual(d1**d2, Decimal('25')) 1303 self.assertEqual(d1**d2, Decimal('25'))
1051 self.assertEqual(d2**d1, Decimal('32')) 1304 self.assertEqual(d2**d1, Decimal('32'))
1052 1305
1053 #with other type, left 1306 #with other type, left
1054 c = d1 ** 4 1307 c = d1 ** 4
1055 self.assertEqual(c, Decimal('625')) 1308 self.assertEqual(c, Decimal('625'))
1056 self.assertEqual(type(c), type(d1)) 1309 self.assertEqual(type(c), type(d1))
1057 1310
1058 #with other type, right 1311 #with other type, right
1059 c = 7 ** d1 1312 c = 7 ** d1
1060 self.assertEqual(c, Decimal('16807')) 1313 self.assertEqual(c, Decimal('16807'))
1061 self.assertEqual(type(c), type(d1)) 1314 self.assertEqual(type(c), type(d1))
1062 1315
1063 #inline with decimal 1316 #inline with decimal
1064 d1 **= d2 1317 d1 **= d2
1065 self.assertEqual(d1, Decimal('25')) 1318 self.assertEqual(d1, Decimal('25'))
1066 1319
1067 #inline with other type 1320 #inline with other type
1068 d1 **= 4 1321 d1 **= 4
1069 self.assertEqual(d1, Decimal('390625')) 1322 self.assertEqual(d1, Decimal('390625'))
1070 1323
1071 def test_module(self): 1324 def test_module(self):
1325 Decimal = self.decimal.Decimal
1072 1326
1073 d1 = Decimal('5') 1327 d1 = Decimal('5')
1074 d2 = Decimal('2') 1328 d2 = Decimal('2')
1075 1329
1076 #two Decimals 1330 #two Decimals
1077 self.assertEqual(d1%d2, Decimal('1')) 1331 self.assertEqual(d1%d2, Decimal('1'))
1078 self.assertEqual(d2%d1, Decimal('2')) 1332 self.assertEqual(d2%d1, Decimal('2'))
1079 1333
1080 #with other type, left 1334 #with other type, left
1081 c = d1 % 4 1335 c = d1 % 4
1082 self.assertEqual(c, Decimal('1')) 1336 self.assertEqual(c, Decimal('1'))
1083 self.assertEqual(type(c), type(d1)) 1337 self.assertEqual(type(c), type(d1))
1084 1338
1085 #with other type, right 1339 #with other type, right
1086 c = 7 % d1 1340 c = 7 % d1
1087 self.assertEqual(c, Decimal('2')) 1341 self.assertEqual(c, Decimal('2'))
1088 self.assertEqual(type(c), type(d1)) 1342 self.assertEqual(type(c), type(d1))
1089 1343
1090 #inline with decimal 1344 #inline with decimal
1091 d1 %= d2 1345 d1 %= d2
1092 self.assertEqual(d1, Decimal('1')) 1346 self.assertEqual(d1, Decimal('1'))
1093 1347
1094 #inline with other type 1348 #inline with other type
1095 d1 %= 4 1349 d1 %= 4
1096 self.assertEqual(d1, Decimal('1')) 1350 self.assertEqual(d1, Decimal('1'))
1097 1351
1098 def test_floor_div_module(self): 1352 def test_floor_div_module(self):
1353 Decimal = self.decimal.Decimal
1099 1354
1100 d1 = Decimal('5') 1355 d1 = Decimal('5')
1101 d2 = Decimal('2') 1356 d2 = Decimal('2')
1102 1357
1103 #two Decimals 1358 #two Decimals
1104 (p, q) = divmod(d1, d2) 1359 (p, q) = divmod(d1, d2)
1105 self.assertEqual(p, Decimal('2')) 1360 self.assertEqual(p, Decimal('2'))
1106 self.assertEqual(q, Decimal('1')) 1361 self.assertEqual(q, Decimal('1'))
1107 self.assertEqual(type(p), type(d1)) 1362 self.assertEqual(type(p), type(d1))
1108 self.assertEqual(type(q), type(d1)) 1363 self.assertEqual(type(q), type(d1))
1109 1364
1110 #with other type, left 1365 #with other type, left
1111 (p, q) = divmod(d1, 4) 1366 (p, q) = divmod(d1, 4)
1112 self.assertEqual(p, Decimal('1')) 1367 self.assertEqual(p, Decimal('1'))
1113 self.assertEqual(q, Decimal('1')) 1368 self.assertEqual(q, Decimal('1'))
1114 self.assertEqual(type(p), type(d1)) 1369 self.assertEqual(type(p), type(d1))
1115 self.assertEqual(type(q), type(d1)) 1370 self.assertEqual(type(q), type(d1))
1116 1371
1117 #with other type, right 1372 #with other type, right
1118 (p, q) = divmod(7, d1) 1373 (p, q) = divmod(7, d1)
1119 self.assertEqual(p, Decimal('1')) 1374 self.assertEqual(p, Decimal('1'))
1120 self.assertEqual(q, Decimal('2')) 1375 self.assertEqual(q, Decimal('2'))
1121 self.assertEqual(type(p), type(d1)) 1376 self.assertEqual(type(p), type(d1))
1122 self.assertEqual(type(q), type(d1)) 1377 self.assertEqual(type(q), type(d1))
1123 1378
1124 def test_unary_operators(self): 1379 def test_unary_operators(self):
1380 Decimal = self.decimal.Decimal
1381
1125 self.assertEqual(+Decimal(45), Decimal(+45)) # + 1382 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1126 self.assertEqual(-Decimal(45), Decimal(-45)) # - 1383 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1127 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs 1384 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1128 1385
1129 def test_nan_comparisons(self): 1386 def test_nan_comparisons(self):
1130 # comparisons involving signaling nans signal InvalidOperation 1387 # comparisons involving signaling nans signal InvalidOperation
1131 1388
1132 # order comparisons (<, <=, >, >=) involving only quiet nans 1389 # order comparisons (<, <=, >, >=) involving only quiet nans
1133 # also signal InvalidOperation 1390 # also signal InvalidOperation
1134 1391
1135 # equality comparisons (==, !=) involving only quiet nans 1392 # equality comparisons (==, !=) involving only quiet nans
1136 # don't signal, but return False or True respectively. 1393 # don't signal, but return False or True respectively.
1394 Decimal = self.decimal.Decimal
1395 InvalidOperation = self.decimal.InvalidOperation
1396 localcontext = self.decimal.localcontext
1137 1397
1138 n = Decimal('NaN') 1398 n = Decimal('NaN')
1139 s = Decimal('sNaN') 1399 s = Decimal('sNaN')
1140 i = Decimal('Inf') 1400 i = Decimal('Inf')
1141 f = Decimal('2') 1401 f = Decimal('2')
1142 1402
1143 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n) 1403 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1144 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s) 1404 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1145 order_ops = operator.lt, operator.le, operator.gt, operator.ge 1405 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1146 equality_ops = operator.eq, operator.ne 1406 equality_ops = operator.eq, operator.ne
(...skipping 25 matching lines...) Expand all
1172 for x, y in snan_pairs: 1432 for x, y in snan_pairs:
1173 for op in equality_ops: 1433 for op in equality_ops:
1174 self.assertRaises(InvalidOperation, operator.eq, x, y) 1434 self.assertRaises(InvalidOperation, operator.eq, x, y)
1175 self.assertRaises(InvalidOperation, operator.ne, x, y) 1435 self.assertRaises(InvalidOperation, operator.ne, x, y)
1176 1436
1177 for x, y in qnan_pairs + snan_pairs: 1437 for x, y in qnan_pairs + snan_pairs:
1178 for op in order_ops: 1438 for op in order_ops:
1179 self.assertRaises(InvalidOperation, op, x, y) 1439 self.assertRaises(InvalidOperation, op, x, y)
1180 1440
1181 def test_copy_sign(self): 1441 def test_copy_sign(self):
1442 Decimal = self.decimal.Decimal
1443
1182 d = Decimal(1).copy_sign(Decimal(-2)) 1444 d = Decimal(1).copy_sign(Decimal(-2))
1183
1184 self.assertEqual(Decimal(1).copy_sign(-2), d) 1445 self.assertEqual(Decimal(1).copy_sign(-2), d)
1185 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2') 1446 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1447
1448 class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1449 decimal = C
1450 class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1451 decimal = P
1186 1452
1187 # The following are two functions used to test threading in the next class 1453 # The following are two functions used to test threading in the next class
1188 1454
1189 def thfunc1(cls): 1455 def thfunc1(cls):
1456 Decimal = cls.decimal.Decimal
1457 InvalidOperation = cls.decimal.InvalidOperation
1458 DivisionByZero = cls.decimal.DivisionByZero
1459 Overflow = cls.decimal.Overflow
1460 Underflow = cls.decimal.Underflow
1461 Inexact = cls.decimal.Inexact
1462 getcontext = cls.decimal.getcontext
1463 localcontext = cls.decimal.localcontext
1464
1190 d1 = Decimal(1) 1465 d1 = Decimal(1)
1191 d3 = Decimal(3) 1466 d3 = Decimal(3)
1192 test1 = d1/d3 1467 test1 = d1/d3
1468
1469 cls.finish1.set()
1193 cls.synchro.wait() 1470 cls.synchro.wait()
1471
1194 test2 = d1/d3 1472 test2 = d1/d3
1195 cls.finish1.set() 1473 with localcontext() as c2:
1474 cls.assertTrue(c2.flags[Inexact])
1475 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1476 cls.assertTrue(c2.flags[DivisionByZero])
1477 with localcontext() as c3:
1478 cls.assertTrue(c3.flags[Inexact])
1479 cls.assertTrue(c3.flags[DivisionByZero])
1480 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1481 cls.assertTrue(c3.flags[InvalidOperation])
1482 del c3
1483 cls.assertFalse(c2.flags[InvalidOperation])
1484 del c2
1196 1485
1197 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333')) 1486 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1198 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333')) 1487 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1488
1489 c1 = getcontext()
1490 cls.assertTrue(c1.flags[Inexact])
1491 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1492 cls.assertFalse(c1.flags[sig])
1199 return 1493 return
1200 1494
1201 def thfunc2(cls): 1495 def thfunc2(cls):
1496 Decimal = cls.decimal.Decimal
1497 InvalidOperation = cls.decimal.InvalidOperation
1498 DivisionByZero = cls.decimal.DivisionByZero
1499 Overflow = cls.decimal.Overflow
1500 Underflow = cls.decimal.Underflow
1501 Inexact = cls.decimal.Inexact
1502 getcontext = cls.decimal.getcontext
1503 localcontext = cls.decimal.localcontext
1504
1202 d1 = Decimal(1) 1505 d1 = Decimal(1)
1203 d3 = Decimal(3) 1506 d3 = Decimal(3)
1204 test1 = d1/d3 1507 test1 = d1/d3
1508
1205 thiscontext = getcontext() 1509 thiscontext = getcontext()
1206 thiscontext.prec = 18 1510 thiscontext.prec = 18
1207 test2 = d1/d3 1511 test2 = d1/d3
1512
1513 with localcontext() as c2:
1514 cls.assertTrue(c2.flags[Inexact])
1515 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1516 cls.assertTrue(c2.flags[Overflow])
1517 with localcontext(thiscontext) as c3:
1518 cls.assertTrue(c3.flags[Inexact])
1519 cls.assertFalse(c3.flags[Overflow])
1520 c3.traps[Underflow] = True
1521 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1522 cls.assertTrue(c3.flags[Underflow])
1523 del c3
1524 cls.assertFalse(c2.flags[Underflow])
1525 cls.assertFalse(c2.traps[Underflow])
1526 del c2
1527
1208 cls.synchro.set() 1528 cls.synchro.set()
1209 cls.finish2.set() 1529 cls.finish2.set()
1210 1530
1211 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333')) 1531 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1212 cls.assertEqual(test2, Decimal('0.333333333333333333')) 1532 cls.assertEqual(test2, Decimal('0.333333333333333333'))
1533
1534 cls.assertFalse(thiscontext.traps[Underflow])
1535 cls.assertTrue(thiscontext.flags[Inexact])
1536 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1537 cls.assertFalse(thiscontext.flags[sig])
1213 return 1538 return
1214 1539
1215 1540 class ThreadingTest(unittest.TestCase):
1216 class DecimalUseOfContextTest(unittest.TestCase): 1541 '''Unit tests for thread local contexts in Decimal.'''
1217 '''Unit tests for Use of Context cases in Decimal.'''
1218
1219 try:
1220 import threading
1221 except ImportError:
1222 threading = None
1223 1542
1224 # Take care executing this test from IDLE, there's an issue in threading 1543 # Take care executing this test from IDLE, there's an issue in threading
1225 # that hangs IDLE and I couldn't find it 1544 # that hangs IDLE and I couldn't find it
1226 1545
1227 def test_threading(self): 1546 def test_threading(self):
1228 #Test the "threading isolation" of a Context. 1547 DefaultContext = self.decimal.DefaultContext
1548
1549 if self.decimal == C and not self.decimal.HAVE_THREADS:
1550 self.skipTest("compiled without threading")
1551 # Test the "threading isolation" of a Context. Also test changing
1552 # the DefaultContext, which acts as a template for the thread-local
1553 # contexts.
1554 save_prec = DefaultContext.prec
1555 save_emax = DefaultContext.Emax
1556 save_emin = DefaultContext.Emin
1557 DefaultContext.prec = 24
1558 DefaultContext.Emax = 425000000
1559 DefaultContext.Emin = -425000000
1229 1560
1230 self.synchro = threading.Event() 1561 self.synchro = threading.Event()
1231 self.finish1 = threading.Event() 1562 self.finish1 = threading.Event()
1232 self.finish2 = threading.Event() 1563 self.finish2 = threading.Event()
1233 1564
1234 th1 = threading.Thread(target=thfunc1, args=(self,)) 1565 th1 = threading.Thread(target=thfunc1, args=(self,))
1235 th2 = threading.Thread(target=thfunc2, args=(self,)) 1566 th2 = threading.Thread(target=thfunc2, args=(self,))
1236 1567
1237 th1.start() 1568 th1.start()
1238 th2.start() 1569 th2.start()
1239 1570
1240 self.finish1.wait() 1571 self.finish1.wait()
1241 self.finish2.wait() 1572 self.finish2.wait()
1573
1574 for sig in Signals[self.decimal]:
1575 self.assertFalse(DefaultContext.flags[sig])
1576
1577 DefaultContext.prec = save_prec
1578 DefaultContext.Emax = save_emax
1579 DefaultContext.Emin = save_emin
1242 return 1580 return
1243 1581
1244 if threading is None: 1582 @unittest.skipUnless(threading, 'threading required')
1245 del test_threading 1583 class CThreadingTest(ThreadingTest):
1584 decimal = C
1585 @unittest.skipUnless(threading, 'threading required')
1586 class PyThreadingTest(ThreadingTest):
1587 decimal = P
1246 1588
1247 1589 class UsabilityTest(unittest.TestCase):
1248 class DecimalUsabilityTest(unittest.TestCase):
1249 '''Unit tests for Usability cases of Decimal.''' 1590 '''Unit tests for Usability cases of Decimal.'''
1250 1591
1251 def test_comparison_operators(self): 1592 def test_comparison_operators(self):
1252 1593
1594 Decimal = self.decimal.Decimal
1595
1253 da = Decimal('23.42') 1596 da = Decimal('23.42')
1254 db = Decimal('23.42') 1597 db = Decimal('23.42')
1255 dc = Decimal('45') 1598 dc = Decimal('45')
1256 1599
1257 #two Decimals 1600 #two Decimals
1258 self.assertGreater(dc, da) 1601 self.assertGreater(dc, da)
1259 self.assertGreaterEqual(dc, da) 1602 self.assertGreaterEqual(dc, da)
1260 self.assertLess(da, dc) 1603 self.assertLess(da, dc)
1261 self.assertLessEqual(da, dc) 1604 self.assertLessEqual(da, dc)
1262 self.assertEqual(da, db) 1605 self.assertEqual(da, db)
(...skipping 13 matching lines...) Expand all
1276 self.assertNotEqual(da, object) 1619 self.assertNotEqual(da, object)
1277 1620
1278 # sortable 1621 # sortable
1279 a = list(map(Decimal, range(100))) 1622 a = list(map(Decimal, range(100)))
1280 b = a[:] 1623 b = a[:]
1281 random.shuffle(a) 1624 random.shuffle(a)
1282 a.sort() 1625 a.sort()
1283 self.assertEqual(a, b) 1626 self.assertEqual(a, b)
1284 1627
1285 def test_decimal_float_comparison(self): 1628 def test_decimal_float_comparison(self):
1629 Decimal = self.decimal.Decimal
1630
1286 da = Decimal('0.25') 1631 da = Decimal('0.25')
1287 db = Decimal('3.0') 1632 db = Decimal('3.0')
1288 self.assertLess(da, 3.0) 1633 self.assertLess(da, 3.0)
1289 self.assertLessEqual(da, 3.0) 1634 self.assertLessEqual(da, 3.0)
1290 self.assertGreater(db, 0.25) 1635 self.assertGreater(db, 0.25)
1291 self.assertGreaterEqual(db, 0.25) 1636 self.assertGreaterEqual(db, 0.25)
1292 self.assertNotEqual(da, 1.5) 1637 self.assertNotEqual(da, 1.5)
1293 self.assertEqual(da, 0.25) 1638 self.assertEqual(da, 0.25)
1294 self.assertGreater(3.0, da) 1639 self.assertGreater(3.0, da)
1295 self.assertGreaterEqual(3.0, da) 1640 self.assertGreaterEqual(3.0, da)
1296 self.assertLess(0.25, db) 1641 self.assertLess(0.25, db)
1297 self.assertLessEqual(0.25, db) 1642 self.assertLessEqual(0.25, db)
1298 self.assertNotEqual(0.25, db) 1643 self.assertNotEqual(0.25, db)
1299 self.assertEqual(3.0, db) 1644 self.assertEqual(3.0, db)
1300 self.assertNotEqual(0.1, Decimal('0.1')) 1645 self.assertNotEqual(0.1, Decimal('0.1'))
1301 1646
1647 def test_decimal_complex_comparison(self):
1648 Decimal = self.decimal.Decimal
1649
1650 da = Decimal('0.25')
1651 db = Decimal('3.0')
1652 self.assertNotEqual(da, (1.5+0j))
1653 self.assertNotEqual((1.5+0j), da)
1654 self.assertEqual(da, (0.25+0j))
1655 self.assertEqual((0.25+0j), da)
1656 self.assertEqual((3.0+0j), db)
1657 self.assertEqual(db, (3.0+0j))
1658
1659 self.assertNotEqual(db, (3.0+1j))
1660 self.assertNotEqual((3.0+1j), db)
1661
1662 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1663 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1664 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1665 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1666
1667 def test_decimal_fraction_comparison(self):
1668 D = self.decimal.Decimal
1669 F = fractions[self.decimal].Fraction
1670 Context = self.decimal.Context
1671 localcontext = self.decimal.localcontext
1672 InvalidOperation = self.decimal.InvalidOperation
1673
1674
1675 emax = C.MAX_EMAX if C else 999999999
1676 emin = C.MIN_EMIN if C else -999999999
1677 etiny = C.MIN_ETINY if C else -1999999997
1678 c = Context(Emax=emax, Emin=emin)
1679
1680 with localcontext(c):
1681 c.prec = emax
1682 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1683 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1684 self.assertLess(F(0,1), D("1e" + str(etiny)))
1685 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1686 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)) )
1687 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999 ))
1688
1689 self.assertEqual(D("0.1"), F(1,10))
1690 self.assertEqual(F(1,10), D("0.1"))
1691
1692 c.prec = 300
1693 self.assertNotEqual(D(1)/3, F(1,3))
1694 self.assertNotEqual(F(1,3), D(1)/3)
1695
1696 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1697 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999 ))
1698
1699 self.assertGreater(D('inf'), F(99999999999,123))
1700 self.assertGreater(D('inf'), F(-99999999999,123))
1701 self.assertLess(D('-inf'), F(99999999999,123))
1702 self.assertLess(D('-inf'), F(-99999999999,123))
1703
1704 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1705 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1706 self.assertNotEqual(D('nan'), F(-9,123))
1707 self.assertNotEqual(F(-9,123), D('nan'))
1708
1302 def test_copy_and_deepcopy_methods(self): 1709 def test_copy_and_deepcopy_methods(self):
1710 Decimal = self.decimal.Decimal
1711
1303 d = Decimal('43.24') 1712 d = Decimal('43.24')
1304 c = copy.copy(d) 1713 c = copy.copy(d)
1305 self.assertEqual(id(c), id(d)) 1714 self.assertEqual(id(c), id(d))
1306 dc = copy.deepcopy(d) 1715 dc = copy.deepcopy(d)
1307 self.assertEqual(id(dc), id(d)) 1716 self.assertEqual(id(dc), id(d))
1308 1717
1309 def test_hash_method(self): 1718 def test_hash_method(self):
1719
1720 Decimal = self.decimal.Decimal
1721 localcontext = self.decimal.localcontext
1722
1310 def hashit(d): 1723 def hashit(d):
1311 a = hash(d) 1724 a = hash(d)
1312 b = d.__hash__() 1725 b = d.__hash__()
1313 self.assertEqual(a, b) 1726 self.assertEqual(a, b)
1314 return a 1727 return a
1315 1728
1316 #just that it's hashable 1729 #just that it's hashable
1317 hashit(Decimal(23)) 1730 hashit(Decimal(23))
1318 hashit(Decimal('Infinity')) 1731 hashit(Decimal('Infinity'))
1319 hashit(Decimal('-Infinity')) 1732 hashit(Decimal('-Infinity'))
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 1773
1361 # check that the hashes of a Decimal float match when they 1774 # check that the hashes of a Decimal float match when they
1362 # represent exactly the same values 1775 # represent exactly the same values
1363 test_strings = ['inf', '-Inf', '0.0', '-.0e1', 1776 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1364 '34.0', '2.5', '112390.625', '-0.515625'] 1777 '34.0', '2.5', '112390.625', '-0.515625']
1365 for s in test_strings: 1778 for s in test_strings:
1366 f = float(s) 1779 f = float(s)
1367 d = Decimal(s) 1780 d = Decimal(s)
1368 self.assertEqual(hashit(f), hashit(d)) 1781 self.assertEqual(hashit(f), hashit(d))
1369 1782
1370 # check that the value of the hash doesn't depend on the 1783 with localcontext() as c:
1371 # current context (issue #1757) 1784 # check that the value of the hash doesn't depend on the
1372 c = getcontext() 1785 # current context (issue #1757)
1373 old_precision = c.prec 1786 x = Decimal("123456789.1")
1374 x = Decimal("123456789.1")
1375 1787
1376 c.prec = 6 1788 c.prec = 6
1377 h1 = hashit(x) 1789 h1 = hashit(x)
1378 c.prec = 10 1790 c.prec = 10
1379 h2 = hashit(x) 1791 h2 = hashit(x)
1380 c.prec = 16 1792 c.prec = 16
1381 h3 = hashit(x) 1793 h3 = hashit(x)
1382 1794
1383 self.assertEqual(h1, h2) 1795 self.assertEqual(h1, h2)
1384 self.assertEqual(h1, h3) 1796 self.assertEqual(h1, h3)
1385 c.prec = old_precision 1797
1798 c.prec = 10000
1799 x = 1100 ** 1248
1800 self.assertEqual(hashit(Decimal(x)), hashit(x))
1386 1801
1387 def test_min_and_max_methods(self): 1802 def test_min_and_max_methods(self):
1803 Decimal = self.decimal.Decimal
1388 1804
1389 d1 = Decimal('15.32') 1805 d1 = Decimal('15.32')
1390 d2 = Decimal('28.5') 1806 d2 = Decimal('28.5')
1391 l1 = 15 1807 l1 = 15
1392 l2 = 28 1808 l2 = 28
1393 1809
1394 #between Decimals 1810 #between Decimals
1395 self.assertIs(min(d1,d2), d1) 1811 self.assertIs(min(d1,d2), d1)
1396 self.assertIs(min(d2,d1), d1) 1812 self.assertIs(min(d2,d1), d1)
1397 self.assertIs(max(d1,d2), d2) 1813 self.assertIs(max(d1,d2), d2)
1398 self.assertIs(max(d2,d1), d2) 1814 self.assertIs(max(d2,d1), d2)
1399 1815
1400 #between Decimal and long 1816 #between Decimal and long
1401 self.assertIs(min(d1,l2), d1) 1817 self.assertIs(min(d1,l2), d1)
1402 self.assertIs(min(l2,d1), d1) 1818 self.assertIs(min(l2,d1), d1)
1403 self.assertIs(max(l1,d2), d2) 1819 self.assertIs(max(l1,d2), d2)
1404 self.assertIs(max(d2,l1), d2) 1820 self.assertIs(max(d2,l1), d2)
1405 1821
1406 def test_as_nonzero(self): 1822 def test_as_nonzero(self):
1823 Decimal = self.decimal.Decimal
1824
1407 #as false 1825 #as false
1408 self.assertFalse(Decimal(0)) 1826 self.assertFalse(Decimal(0))
1409 #as true 1827 #as true
1410 self.assertTrue(Decimal('0.372')) 1828 self.assertTrue(Decimal('0.372'))
1411 1829
1412 def test_tostring_methods(self): 1830 def test_tostring_methods(self):
1413 #Test str and repr methods. 1831 #Test str and repr methods.
1832 Decimal = self.decimal.Decimal
1414 1833
1415 d = Decimal('15.32') 1834 d = Decimal('15.32')
1416 self.assertEqual(str(d), '15.32') # str 1835 self.assertEqual(str(d), '15.32') # str
1417 self.assertEqual(repr(d), "Decimal('15.32')") # repr 1836 self.assertEqual(repr(d), "Decimal('15.32')") # repr
1418 1837
1419 def test_tonum_methods(self): 1838 def test_tonum_methods(self):
1420 #Test float and int methods. 1839 #Test float and int methods.
1840 Decimal = self.decimal.Decimal
1421 1841
1422 d1 = Decimal('66') 1842 d1 = Decimal('66')
1423 d2 = Decimal('15.32') 1843 d2 = Decimal('15.32')
1424 1844
1425 #int 1845 #int
1426 self.assertEqual(int(d1), 66) 1846 self.assertEqual(int(d1), 66)
1427 self.assertEqual(int(d2), 15) 1847 self.assertEqual(int(d2), 15)
1428 1848
1429 #float 1849 #float
1430 self.assertEqual(float(d1), 66) 1850 self.assertEqual(float(d1), 66)
1431 self.assertEqual(float(d2), 15.32) 1851 self.assertEqual(float(d2), 15.32)
1432 1852
1433 #floor 1853 #floor
1434 test_pairs = [ 1854 test_pairs = [
1435 ('123.00', 123), 1855 ('123.00', 123),
1436 ('3.2', 3), 1856 ('3.2', 3),
1437 ('3.54', 3), 1857 ('3.54', 3),
1438 ('3.899', 3), 1858 ('3.899', 3),
1439 ('-2.3', -3), 1859 ('-2.3', -3),
1440 ('-11.0', -11), 1860 ('-11.0', -11),
1441 ('0.0', 0), 1861 ('0.0', 0),
1442 ('-0E3', 0), 1862 ('-0E3', 0),
1863 ('89891211712379812736.1', 89891211712379812736),
1443 ] 1864 ]
1444 for d, i in test_pairs: 1865 for d, i in test_pairs:
1445 self.assertEqual(math.floor(Decimal(d)), i) 1866 self.assertEqual(math.floor(Decimal(d)), i)
1446 self.assertRaises(ValueError, math.floor, Decimal('-NaN')) 1867 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1447 self.assertRaises(ValueError, math.floor, Decimal('sNaN')) 1868 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1448 self.assertRaises(ValueError, math.floor, Decimal('NaN123')) 1869 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1449 self.assertRaises(OverflowError, math.floor, Decimal('Inf')) 1870 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1450 self.assertRaises(OverflowError, math.floor, Decimal('-Inf')) 1871 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1451 1872
1452 #ceiling 1873 #ceiling
1453 test_pairs = [ 1874 test_pairs = [
1454 ('123.00', 123), 1875 ('123.00', 123),
1455 ('3.2', 4), 1876 ('3.2', 4),
1456 ('3.54', 4), 1877 ('3.54', 4),
1457 ('3.899', 4), 1878 ('3.899', 4),
1458 ('-2.3', -2), 1879 ('-2.3', -2),
1459 ('-11.0', -11), 1880 ('-11.0', -11),
1460 ('0.0', 0), 1881 ('0.0', 0),
1461 ('-0E3', 0), 1882 ('-0E3', 0),
1883 ('89891211712379812736.1', 89891211712379812737),
1462 ] 1884 ]
1463 for d, i in test_pairs: 1885 for d, i in test_pairs:
1464 self.assertEqual(math.ceil(Decimal(d)), i) 1886 self.assertEqual(math.ceil(Decimal(d)), i)
1465 self.assertRaises(ValueError, math.ceil, Decimal('-NaN')) 1887 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1466 self.assertRaises(ValueError, math.ceil, Decimal('sNaN')) 1888 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1467 self.assertRaises(ValueError, math.ceil, Decimal('NaN123')) 1889 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1468 self.assertRaises(OverflowError, math.ceil, Decimal('Inf')) 1890 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1469 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf')) 1891 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1470 1892
1471 #round, single argument 1893 #round, single argument
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1509 ('123.456', 4, '123.4560'), 1931 ('123.456', 4, '123.4560'),
1510 ('123.455', 2, '123.46'), 1932 ('123.455', 2, '123.46'),
1511 ('123.445', 2, '123.44'), 1933 ('123.445', 2, '123.44'),
1512 ('Inf', 4, 'NaN'), 1934 ('Inf', 4, 'NaN'),
1513 ('-Inf', -23, 'NaN'), 1935 ('-Inf', -23, 'NaN'),
1514 ('sNaN314', 3, 'NaN314'), 1936 ('sNaN314', 3, 'NaN314'),
1515 ] 1937 ]
1516 for d, n, r in test_triples: 1938 for d, n, r in test_triples:
1517 self.assertEqual(str(round(Decimal(d), n)), r) 1939 self.assertEqual(str(round(Decimal(d), n)), r)
1518 1940
1519
1520
1521 def test_eval_round_trip(self): 1941 def test_eval_round_trip(self):
1942 Decimal = self.decimal.Decimal
1522 1943
1523 #with zero 1944 #with zero
1524 d = Decimal( (0, (0,), 0) ) 1945 d = Decimal( (0, (0,), 0) )
1525 self.assertEqual(d, eval(repr(d))) 1946 self.assertEqual(d, eval(repr(d)))
1526 1947
1527 #int 1948 #int
1528 d = Decimal( (1, (4, 5), 0) ) 1949 d = Decimal( (1, (4, 5), 0) )
1529 self.assertEqual(d, eval(repr(d))) 1950 self.assertEqual(d, eval(repr(d)))
1530 1951
1531 #float 1952 #float
1532 d = Decimal( (0, (4, 5, 3, 4), -2) ) 1953 d = Decimal( (0, (4, 5, 3, 4), -2) )
1533 self.assertEqual(d, eval(repr(d))) 1954 self.assertEqual(d, eval(repr(d)))
1534 1955
1535 #weird 1956 #weird
1536 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) ) 1957 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1537 self.assertEqual(d, eval(repr(d))) 1958 self.assertEqual(d, eval(repr(d)))
1538 1959
1539 def test_as_tuple(self): 1960 def test_as_tuple(self):
1961 Decimal = self.decimal.Decimal
1540 1962
1541 #with zero 1963 #with zero
1542 d = Decimal(0) 1964 d = Decimal(0)
1543 self.assertEqual(d.as_tuple(), (0, (0,), 0) ) 1965 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1544 1966
1545 #int 1967 #int
1546 d = Decimal(-45) 1968 d = Decimal(-45)
1547 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) ) 1969 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1548 1970
1549 #complicated string 1971 #complicated string
1550 d = Decimal("-4.34913534E-17") 1972 d = Decimal("-4.34913534E-17")
1551 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) ) 1973 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1552 1974
1553 #inf 1975 # XXX non-compliant infinity payload.
1554 d = Decimal("Infinity") 1976 d = Decimal("Infinity")
1555 self.assertEqual(d.as_tuple(), (0, (0,), 'F') ) 1977 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1556 1978
1557 #leading zeros in coefficient should be stripped 1979 #leading zeros in coefficient should be stripped
1558 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) ) 1980 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1559 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) ) 1981 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1560 d = Decimal( (1, (0, 0, 0), 37) ) 1982 d = Decimal( (1, (0, 0, 0), 37) )
1561 self.assertEqual(d.as_tuple(), (1, (0,), 37)) 1983 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1562 d = Decimal( (1, (), 37) ) 1984 d = Decimal( (1, (), 37) )
1563 self.assertEqual(d.as_tuple(), (1, (0,), 37)) 1985 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1564 1986
1565 #leading zeros in NaN diagnostic info should be stripped 1987 #leading zeros in NaN diagnostic info should be stripped
1566 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') ) 1988 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1567 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') ) 1989 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1568 d = Decimal( (1, (0, 0, 0), 'N') ) 1990 d = Decimal( (1, (0, 0, 0), 'N') )
1569 self.assertEqual(d.as_tuple(), (1, (), 'N') ) 1991 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1570 d = Decimal( (1, (), 'n') ) 1992 d = Decimal( (1, (), 'n') )
1571 self.assertEqual(d.as_tuple(), (1, (), 'n') ) 1993 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1572 1994
1573 #coefficient in infinity should be ignored 1995 # XXX coefficient in infinity should raise an error
1574 d = Decimal( (0, (4, 5, 3, 4), 'F') ) 1996 if self.decimal == P:
1575 self.assertEqual(d.as_tuple(), (0, (0,), 'F')) 1997 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1576 d = Decimal( (1, (0, 2, 7, 1), 'F') ) 1998 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1577 self.assertEqual(d.as_tuple(), (1, (0,), 'F')) 1999 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1578 2000 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1579 def test_immutability_operations(self): 2001
2002 def test_subclassing(self):
2003 # Different behaviours when subclassing Decimal
2004 Decimal = self.decimal.Decimal
2005
2006 class MyDecimal(Decimal):
2007 pass
2008
2009 d1 = MyDecimal(1)
2010 d2 = MyDecimal(2)
2011 d = d1 + d2
2012 self.assertIs(type(d), Decimal)
2013
2014 d = d1.max(d2)
2015 self.assertIs(type(d), Decimal)
2016
2017 d = copy.copy(d1)
2018 self.assertIs(type(d), MyDecimal)
2019 self.assertEqual(d, d1)
2020
2021 d = copy.deepcopy(d1)
2022 self.assertIs(type(d), MyDecimal)
2023 self.assertEqual(d, d1)
2024
2025 def test_implicit_context(self):
2026 Decimal = self.decimal.Decimal
2027 getcontext = self.decimal.getcontext
2028
2029 # Check results when context given implicitly. (Issue 2478)
2030 c = getcontext()
2031 self.assertEqual(str(Decimal(0).sqrt()),
2032 str(c.sqrt(Decimal(0))))
2033
2034 def test_conversions_from_int(self):
2035 # Check that methods taking a second Decimal argument will
2036 # always accept an integer in place of a Decimal.
2037 Decimal = self.decimal.Decimal
2038
2039 self.assertEqual(Decimal(4).compare(3),
2040 Decimal(4).compare(Decimal(3)))
2041 self.assertEqual(Decimal(4).compare_signal(3),
2042 Decimal(4).compare_signal(Decimal(3)))
2043 self.assertEqual(Decimal(4).compare_total(3),
2044 Decimal(4).compare_total(Decimal(3)))
2045 self.assertEqual(Decimal(4).compare_total_mag(3),
2046 Decimal(4).compare_total_mag(Decimal(3)))
2047 self.assertEqual(Decimal(10101).logical_and(1001),
2048 Decimal(10101).logical_and(Decimal(1001)))
2049 self.assertEqual(Decimal(10101).logical_or(1001),
2050 Decimal(10101).logical_or(Decimal(1001)))
2051 self.assertEqual(Decimal(10101).logical_xor(1001),
2052 Decimal(10101).logical_xor(Decimal(1001)))
2053 self.assertEqual(Decimal(567).max(123),
2054 Decimal(567).max(Decimal(123)))
2055 self.assertEqual(Decimal(567).max_mag(123),
2056 Decimal(567).max_mag(Decimal(123)))
2057 self.assertEqual(Decimal(567).min(123),
2058 Decimal(567).min(Decimal(123)))
2059 self.assertEqual(Decimal(567).min_mag(123),
2060 Decimal(567).min_mag(Decimal(123)))
2061 self.assertEqual(Decimal(567).next_toward(123),
2062 Decimal(567).next_toward(Decimal(123)))
2063 self.assertEqual(Decimal(1234).quantize(100),
2064 Decimal(1234).quantize(Decimal(100)))
2065 self.assertEqual(Decimal(768).remainder_near(1234),
2066 Decimal(768).remainder_near(Decimal(1234)))
2067 self.assertEqual(Decimal(123).rotate(1),
2068 Decimal(123).rotate(Decimal(1)))
2069 self.assertEqual(Decimal(1234).same_quantum(1000),
2070 Decimal(1234).same_quantum(Decimal(1000)))
2071 self.assertEqual(Decimal('9.123').scaleb(-100),
2072 Decimal('9.123').scaleb(Decimal(-100)))
2073 self.assertEqual(Decimal(456).shift(-1),
2074 Decimal(456).shift(Decimal(-1)))
2075
2076 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2077 Decimal(-12).fma(Decimal(45), Decimal(67)))
2078 self.assertEqual(Decimal(-12).fma(45, 67),
2079 Decimal(-12).fma(Decimal(45), Decimal(67)))
2080 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2081 Decimal(-12).fma(Decimal(45), Decimal(67)))
2082
2083 class CUsabilityTest(UsabilityTest):
2084 decimal = C
2085 class PyUsabilityTest(UsabilityTest):
2086 decimal = P
2087
2088 class PythonAPItests(unittest.TestCase):
2089
2090 def test_abc(self):
2091 Decimal = self.decimal.Decimal
2092
2093 self.assertTrue(issubclass(Decimal, numbers.Number))
2094 self.assertFalse(issubclass(Decimal, numbers.Real))
2095 self.assertIsInstance(Decimal(0), numbers.Number)
2096 self.assertNotIsInstance(Decimal(0), numbers.Real)
2097
2098 def test_pickle(self):
2099 Decimal = self.decimal.Decimal
2100
2101 savedecimal = sys.modules['decimal']
2102
2103 # Round trip
2104 sys.modules['decimal'] = self.decimal
2105 d = Decimal('-3.141590000')
2106 p = pickle.dumps(d)
2107 e = pickle.loads(p)
2108 self.assertEqual(d, e)
2109
2110 if C:
2111 # Test interchangeability
2112 x = C.Decimal('-3.123e81723')
2113 y = P.Decimal('-3.123e81723')
2114
2115 sys.modules['decimal'] = C
2116 sx = pickle.dumps(x)
2117 sys.modules['decimal'] = P
2118 r = pickle.loads(sx)
2119 self.assertIsInstance(r, P.Decimal)
2120 self.assertEqual(r, y)
2121
2122 sys.modules['decimal'] = P
2123 sy = pickle.dumps(y)
2124 sys.modules['decimal'] = C
2125 r = pickle.loads(sy)
2126 self.assertIsInstance(r, C.Decimal)
2127 self.assertEqual(r, x)
2128
2129 sys.modules['decimal'] = savedecimal
2130
2131 def test_int(self):
2132 Decimal = self.decimal.Decimal
2133 ROUND_DOWN = self.decimal.ROUND_DOWN
2134
2135 for x in range(-250, 250):
2136 s = '%0.2f' % (x / 100.0)
2137 # should work the same as for floats
2138 self.assertEqual(int(Decimal(s)), int(float(s)))
2139 # should work the same as to_integral in the ROUND_DOWN mode
2140 d = Decimal(s)
2141 r = d.to_integral(ROUND_DOWN)
2142 self.assertEqual(Decimal(int(d)), r)
2143
2144 self.assertRaises(ValueError, int, Decimal('-nan'))
2145 self.assertRaises(ValueError, int, Decimal('snan'))
2146 self.assertRaises(OverflowError, int, Decimal('inf'))
2147 self.assertRaises(OverflowError, int, Decimal('-inf'))
2148
2149 def test_trunc(self):
2150 Decimal = self.decimal.Decimal
2151 ROUND_DOWN = self.decimal.ROUND_DOWN
2152
2153 for x in range(-250, 250):
2154 s = '%0.2f' % (x / 100.0)
2155 # should work the same as for floats
2156 self.assertEqual(int(Decimal(s)), int(float(s)))
2157 # should work the same as to_integral in the ROUND_DOWN mode
2158 d = Decimal(s)
2159 r = d.to_integral(ROUND_DOWN)
2160 self.assertEqual(Decimal(math.trunc(d)), r)
2161
2162 def test_from_float(self):
2163
2164 Decimal = self.decimal.Decimal
2165
2166 class MyDecimal(Decimal):
2167 pass
2168
2169 self.assertTrue(issubclass(MyDecimal, Decimal))
2170
2171 r = MyDecimal.from_float(0.1)
2172 self.assertEqual(type(r), MyDecimal)
2173 self.assertEqual(str(r),
2174 '0.1000000000000000055511151231257827021181583404541015625')
2175 bigint = 12345678901234567890123456789
2176 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2177 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2178 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2179 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2180 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2181 str(Decimal('NaN')))
2182 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2183 str(Decimal('Infinity')))
2184 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2185 str(Decimal('-Infinity')))
2186 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2187 for i in range(200):
2188 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2189 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2190
2191 def test_create_decimal_from_float(self):
2192 Decimal = self.decimal.Decimal
2193 Context = self.decimal.Context
2194 ROUND_DOWN = self.decimal.ROUND_DOWN
2195 ROUND_UP = self.decimal.ROUND_UP
2196 Inexact = self.decimal.Inexact
2197
2198 context = Context(prec=5, rounding=ROUND_DOWN)
2199 self.assertEqual(
2200 context.create_decimal_from_float(math.pi),
2201 Decimal('3.1415')
2202 )
2203 context = Context(prec=5, rounding=ROUND_UP)
2204 self.assertEqual(
2205 context.create_decimal_from_float(math.pi),
2206 Decimal('3.1416')
2207 )
2208 context = Context(prec=5, traps=[Inexact])
2209 self.assertRaises(
2210 Inexact,
2211 context.create_decimal_from_float,
2212 math.pi
2213 )
2214 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2215 "Decimal('-0')")
2216 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2217 "Decimal('1')")
2218 self.assertEqual(repr(context.create_decimal_from_float(10)),
2219 "Decimal('10')")
2220
2221 def test_quantize(self):
2222 Decimal = self.decimal.Decimal
2223 Context = self.decimal.Context
2224 InvalidOperation = self.decimal.InvalidOperation
2225 ROUND_DOWN = self.decimal.ROUND_DOWN
2226
2227 c = Context(Emax=99999, Emin=-99999)
2228 self.assertEqual(
2229 Decimal('7.335').quantize(Decimal('.01')),
2230 Decimal('7.34')
2231 )
2232 self.assertEqual(
2233 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2234 Decimal('7.33')
2235 )
2236 self.assertRaises(
2237 InvalidOperation,
2238 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2239 )
2240
2241 c = Context()
2242 d = Decimal("0.871831e800")
2243 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2244 self.assertEqual(x, Decimal('8.71E+799'))
2245
2246 def test_complex(self):
2247 Decimal = self.decimal.Decimal
2248
2249 x = Decimal("9.8182731e181273")
2250 self.assertEqual(x.real, x)
2251 self.assertEqual(x.imag, 0)
2252 self.assertEqual(x.conjugate(), x)
2253
2254 x = Decimal("1")
2255 self.assertEqual(complex(x), complex(float(1)))
2256
2257 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2258 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2259 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2260 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2261
2262 def test_named_parameters(self):
2263 D = self.decimal.Decimal
2264 Context = self.decimal.Context
2265 localcontext = self.decimal.localcontext
2266 InvalidOperation = self.decimal.InvalidOperation
2267 Overflow = self.decimal.Overflow
2268
2269 xc = Context()
2270 xc.prec = 1
2271 xc.Emax = 1
2272 xc.Emin = -1
2273
2274 with localcontext() as c:
2275 c.clear_flags()
2276
2277 self.assertEqual(D(9, xc), 9)
2278 self.assertEqual(D(9, context=xc), 9)
2279 self.assertEqual(D(context=xc, value=9), 9)
2280 self.assertEqual(D(context=xc), 0)
2281 xc.clear_flags()
2282 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2283 self.assertTrue(xc.flags[InvalidOperation])
2284 self.assertFalse(c.flags[InvalidOperation])
2285
2286 xc.clear_flags()
2287 self.assertEqual(D(2).exp(context=xc), 7)
2288 self.assertRaises(Overflow, D(8).exp, context=xc)
2289 self.assertTrue(xc.flags[Overflow])
2290 self.assertFalse(c.flags[Overflow])
2291
2292 xc.clear_flags()
2293 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2294 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2295 self.assertTrue(xc.flags[InvalidOperation])
2296 self.assertFalse(c.flags[InvalidOperation])
2297
2298 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2299 self.assertEqual(D(-1).next_minus(context=xc), -2)
2300 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2301 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2302 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2303 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2304 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2305 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2306
2307 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2308 xc.clear_flags()
2309 self.assertRaises(InvalidOperation,
2310 D("0").compare_signal, D('nan'), context=xc)
2311 self.assertTrue(xc.flags[InvalidOperation])
2312 self.assertFalse(c.flags[InvalidOperation])
2313 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2314 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2315 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2316 D('-0.3'))
2317 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2318 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2319 D('0.0'))
2320 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1') )
2321 xc.clear_flags()
2322 self.assertRaises(InvalidOperation,
2323 D("0.2").quantize, D('1e10'), context=xc)
2324 self.assertTrue(xc.flags[InvalidOperation])
2325 self.assertFalse(c.flags[InvalidOperation])
2326 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2327 D('-0.5'))
2328
2329 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2330 D('7E+1'))
2331
2332 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2333 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2334 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2335 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2336 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2337 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2338 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2339 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2340
2341 self.assertFalse(D("0.01").is_normal(context=xc))
2342 self.assertTrue(D("0.01").is_subnormal(context=xc))
2343
2344 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2345 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2346 self.assertRaises(TypeError, D(1).radix, context=xc)
2347
2348 self.assertEqual(D(-111).logb(context=xc), 2)
2349 self.assertEqual(D(0).logical_invert(context=xc), 1)
2350 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2351 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2352
2353 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2354 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2355 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2356 self.assertEqual(D('23').rotate(1, context=xc), 3)
2357 self.assertEqual(D('23').rotate(1, context=xc), 3)
2358 xc.clear_flags()
2359 self.assertRaises(Overflow,
2360 D('23').scaleb, 1, context=xc)
2361 self.assertTrue(xc.flags[Overflow])
2362 self.assertFalse(c.flags[Overflow])
2363 self.assertEqual(D('23').shift(-1, context=xc), 0)
2364
2365 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2366 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2367
2368 if (self.decimal == C):
2369 self.assertRaises(TypeError, D(1).canonical, context=xc)
2370 self.assertEqual(D("-1").copy_abs(context=xc), 1)
2371 self.assertEqual(D("1").copy_negate(context=xc), -1)
2372 else:
2373 self.assertEqual(D(1).canonical(context=xc), 1)
2374 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2375 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2376
2377 class CPythonAPItests(PythonAPItests):
2378 decimal = C
2379 class PyPythonAPItests(PythonAPItests):
2380 decimal = P
2381
2382 class ContextAPItests(unittest.TestCase):
2383
2384 def test_pickle(self):
2385
2386 Context = self.decimal.Context
2387
2388 savedecimal = sys.modules['decimal']
2389
2390 # Round trip
2391 sys.modules['decimal'] = self.decimal
2392 c = Context()
2393 e = pickle.loads(pickle.dumps(c))
2394
2395 self.assertEqual(c.prec, e.prec)
2396 self.assertEqual(c.Emin, e.Emin)
2397 self.assertEqual(c.Emax, e.Emax)
2398 self.assertEqual(c.rounding, e.rounding)
2399 self.assertEqual(c.capitals, e.capitals)
2400 self.assertEqual(c.clamp, e.clamp)
2401 self.assertEqual(c.flags, e.flags)
2402 self.assertEqual(c.traps, e.traps)
2403
2404 # Test interchangeability
2405 combinations = [(C, P), (P, C)] if C else [(P, P)]
2406 for dumper, loader in combinations:
2407 for ri, _ in enumerate(RoundingModes[dumper]):
2408 for fi, _ in enumerate(OrderedSignals[dumper]):
2409 for ti, _ in enumerate(OrderedSignals[dumper]):
2410
2411 prec = random.randrange(1, 100)
2412 emin = random.randrange(-100, 0)
2413 emax = random.randrange(1, 100)
2414 caps = random.randrange(2)
2415 clamp = random.randrange(2)
2416
2417 # One module dumps
2418 sys.modules['decimal'] = dumper
2419 c = dumper.Context(
2420 prec=prec, Emin=emin, Emax=emax,
2421 rounding=RoundingModes[dumper][ri],
2422 capitals=caps, clamp=clamp,
2423 flags=OrderedSignals[dumper][:fi],
2424 traps=OrderedSignals[dumper][:ti]
2425 )
2426 s = pickle.dumps(c)
2427
2428 # The other module loads
2429 sys.modules['decimal'] = loader
2430 d = pickle.loads(s)
2431 self.assertIsInstance(d, loader.Context)
2432
2433 self.assertEqual(d.prec, prec)
2434 self.assertEqual(d.Emin, emin)
2435 self.assertEqual(d.Emax, emax)
2436 self.assertEqual(d.rounding, RoundingModes[loader][ri])
2437 self.assertEqual(d.capitals, caps)
2438 self.assertEqual(d.clamp, clamp)
2439 assert_signals(self, d, 'flags', OrderedSignals[loader][ :fi])
2440 assert_signals(self, d, 'traps', OrderedSignals[loader][ :ti])
2441
2442 sys.modules['decimal'] = savedecimal
2443
2444 def test_equality_with_other_types(self):
2445 Decimal = self.decimal.Decimal
2446
2447 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2448 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2449
2450 def test_copy(self):
2451 # All copies should be deep
2452 Decimal = self.decimal.Decimal
2453 Context = self.decimal.Context
2454
2455 c = Context()
2456 d = c.copy()
2457 self.assertNotEqual(id(c), id(d))
2458 self.assertNotEqual(id(c.flags), id(d.flags))
2459 self.assertNotEqual(id(c.traps), id(d.traps))
2460 k1 = set(c.flags.keys())
2461 k2 = set(d.flags.keys())
2462 self.assertEqual(k1, k2)
2463 self.assertEqual(c.flags, d.flags)
2464
2465 def test__clamp(self):
2466 # In Python 3.2, the private attribute `_clamp` was made
2467 # public (issue 8540), with the old `_clamp` becoming a
2468 # property wrapping `clamp`. For the duration of Python 3.2
2469 # only, the attribute should be gettable/settable via both
2470 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2471 # removed.
2472 Context = self.decimal.Context
2473 c = Context()
2474 self.assertRaises(AttributeError, getattr, c, '_clamp')
2475
2476 def test_abs(self):
2477 Decimal = self.decimal.Decimal
2478 Context = self.decimal.Context
2479
2480 c = Context()
2481 d = c.abs(Decimal(-1))
2482 self.assertEqual(c.abs(-1), d)
2483 self.assertRaises(TypeError, c.abs, '-1')
2484
2485 def test_add(self):
2486 Decimal = self.decimal.Decimal
2487 Context = self.decimal.Context
2488
2489 c = Context()
2490 d = c.add(Decimal(1), Decimal(1))
2491 self.assertEqual(c.add(1, 1), d)
2492 self.assertEqual(c.add(Decimal(1), 1), d)
2493 self.assertEqual(c.add(1, Decimal(1)), d)
2494 self.assertRaises(TypeError, c.add, '1', 1)
2495 self.assertRaises(TypeError, c.add, 1, '1')
2496
2497 def test_compare(self):
2498 Decimal = self.decimal.Decimal
2499 Context = self.decimal.Context
2500
2501 c = Context()
2502 d = c.compare(Decimal(1), Decimal(1))
2503 self.assertEqual(c.compare(1, 1), d)
2504 self.assertEqual(c.compare(Decimal(1), 1), d)
2505 self.assertEqual(c.compare(1, Decimal(1)), d)
2506 self.assertRaises(TypeError, c.compare, '1', 1)
2507 self.assertRaises(TypeError, c.compare, 1, '1')
2508
2509 def test_compare_signal(self):
2510 Decimal = self.decimal.Decimal
2511 Context = self.decimal.Context
2512
2513 c = Context()
2514 d = c.compare_signal(Decimal(1), Decimal(1))
2515 self.assertEqual(c.compare_signal(1, 1), d)
2516 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2517 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2518 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2519 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2520
2521 def test_compare_total(self):
2522 Decimal = self.decimal.Decimal
2523 Context = self.decimal.Context
2524
2525 c = Context()
2526 d = c.compare_total(Decimal(1), Decimal(1))
2527 self.assertEqual(c.compare_total(1, 1), d)
2528 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2529 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2530 self.assertRaises(TypeError, c.compare_total, '1', 1)
2531 self.assertRaises(TypeError, c.compare_total, 1, '1')
2532
2533 def test_compare_total_mag(self):
2534 Decimal = self.decimal.Decimal
2535 Context = self.decimal.Context
2536
2537 c = Context()
2538 d = c.compare_total_mag(Decimal(1), Decimal(1))
2539 self.assertEqual(c.compare_total_mag(1, 1), d)
2540 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2541 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2542 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2543 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2544
2545 def test_copy_abs(self):
2546 Decimal = self.decimal.Decimal
2547 Context = self.decimal.Context
2548
2549 c = Context()
2550 d = c.copy_abs(Decimal(-1))
2551 self.assertEqual(c.copy_abs(-1), d)
2552 self.assertRaises(TypeError, c.copy_abs, '-1')
2553
2554 def test_copy_decimal(self):
2555 Decimal = self.decimal.Decimal
2556 Context = self.decimal.Context
2557
2558 c = Context()
2559 d = c.copy_decimal(Decimal(-1))
2560 self.assertEqual(c.copy_decimal(-1), d)
2561 self.assertRaises(TypeError, c.copy_decimal, '-1')
2562
2563 def test_copy_negate(self):
2564 Decimal = self.decimal.Decimal
2565 Context = self.decimal.Context
2566
2567 c = Context()
2568 d = c.copy_negate(Decimal(-1))
2569 self.assertEqual(c.copy_negate(-1), d)
2570 self.assertRaises(TypeError, c.copy_negate, '-1')
2571
2572 def test_copy_sign(self):
2573 Decimal = self.decimal.Decimal
2574 Context = self.decimal.Context
2575
2576 c = Context()
2577 d = c.copy_sign(Decimal(1), Decimal(-2))
2578 self.assertEqual(c.copy_sign(1, -2), d)
2579 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2580 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2581 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2582 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2583
2584 def test_divide(self):
2585 Decimal = self.decimal.Decimal
2586 Context = self.decimal.Context
2587
2588 c = Context()
2589 d = c.divide(Decimal(1), Decimal(2))
2590 self.assertEqual(c.divide(1, 2), d)
2591 self.assertEqual(c.divide(Decimal(1), 2), d)
2592 self.assertEqual(c.divide(1, Decimal(2)), d)
2593 self.assertRaises(TypeError, c.divide, '1', 2)
2594 self.assertRaises(TypeError, c.divide, 1, '2')
2595
2596 def test_divide_int(self):
2597 Decimal = self.decimal.Decimal
2598 Context = self.decimal.Context
2599
2600 c = Context()
2601 d = c.divide_int(Decimal(1), Decimal(2))
2602 self.assertEqual(c.divide_int(1, 2), d)
2603 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2604 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2605 self.assertRaises(TypeError, c.divide_int, '1', 2)
2606 self.assertRaises(TypeError, c.divide_int, 1, '2')
2607
2608 def test_divmod(self):
2609 Decimal = self.decimal.Decimal
2610 Context = self.decimal.Context
2611
2612 c = Context()
2613 d = c.divmod(Decimal(1), Decimal(2))
2614 self.assertEqual(c.divmod(1, 2), d)
2615 self.assertEqual(c.divmod(Decimal(1), 2), d)
2616 self.assertEqual(c.divmod(1, Decimal(2)), d)
2617 self.assertRaises(TypeError, c.divmod, '1', 2)
2618 self.assertRaises(TypeError, c.divmod, 1, '2')
2619
2620 def test_exp(self):
2621 Decimal = self.decimal.Decimal
2622 Context = self.decimal.Context
2623
2624 c = Context()
2625 d = c.exp(Decimal(10))
2626 self.assertEqual(c.exp(10), d)
2627 self.assertRaises(TypeError, c.exp, '10')
2628
2629 def test_fma(self):
2630 Decimal = self.decimal.Decimal
2631 Context = self.decimal.Context
2632
2633 c = Context()
2634 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
2635 self.assertEqual(c.fma(2, 3, 4), d)
2636 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
2637 self.assertEqual(c.fma(2, Decimal(3), 4), d)
2638 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
2639 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
2640 self.assertRaises(TypeError, c.fma, '2', 3, 4)
2641 self.assertRaises(TypeError, c.fma, 2, '3', 4)
2642 self.assertRaises(TypeError, c.fma, 2, 3, '4')
2643
2644 # Issue 12079 for Context.fma ...
2645 self.assertRaises(TypeError, c.fma,
2646 Decimal('Infinity'), Decimal(0), "not a decimal")
2647 self.assertRaises(TypeError, c.fma,
2648 Decimal(1), Decimal('snan'), 1.222)
2649 # ... and for Decimal.fma.
2650 self.assertRaises(TypeError, Decimal('Infinity').fma,
2651 Decimal(0), "not a decimal")
2652 self.assertRaises(TypeError, Decimal(1).fma,
2653 Decimal('snan'), 1.222)
2654
2655 def test_is_finite(self):
2656 Decimal = self.decimal.Decimal
2657 Context = self.decimal.Context
2658
2659 c = Context()
2660 d = c.is_finite(Decimal(10))
2661 self.assertEqual(c.is_finite(10), d)
2662 self.assertRaises(TypeError, c.is_finite, '10')
2663
2664 def test_is_infinite(self):
2665 Decimal = self.decimal.Decimal
2666 Context = self.decimal.Context
2667
2668 c = Context()
2669 d = c.is_infinite(Decimal(10))
2670 self.assertEqual(c.is_infinite(10), d)
2671 self.assertRaises(TypeError, c.is_infinite, '10')
2672
2673 def test_is_nan(self):
2674 Decimal = self.decimal.Decimal
2675 Context = self.decimal.Context
2676
2677 c = Context()
2678 d = c.is_nan(Decimal(10))
2679 self.assertEqual(c.is_nan(10), d)
2680 self.assertRaises(TypeError, c.is_nan, '10')
2681
2682 def test_is_normal(self):
2683 Decimal = self.decimal.Decimal
2684 Context = self.decimal.Context
2685
2686 c = Context()
2687 d = c.is_normal(Decimal(10))
2688 self.assertEqual(c.is_normal(10), d)
2689 self.assertRaises(TypeError, c.is_normal, '10')
2690
2691 def test_is_qnan(self):
2692 Decimal = self.decimal.Decimal
2693 Context = self.decimal.Context
2694
2695 c = Context()
2696 d = c.is_qnan(Decimal(10))
2697 self.assertEqual(c.is_qnan(10), d)
2698 self.assertRaises(TypeError, c.is_qnan, '10')
2699
2700 def test_is_signed(self):
2701 Decimal = self.decimal.Decimal
2702 Context = self.decimal.Context
2703
2704 c = Context()
2705 d = c.is_signed(Decimal(10))
2706 self.assertEqual(c.is_signed(10), d)
2707 self.assertRaises(TypeError, c.is_signed, '10')
2708
2709 def test_is_snan(self):
2710 Decimal = self.decimal.Decimal
2711 Context = self.decimal.Context
2712
2713 c = Context()
2714 d = c.is_snan(Decimal(10))
2715 self.assertEqual(c.is_snan(10), d)
2716 self.assertRaises(TypeError, c.is_snan, '10')
2717
2718 def test_is_subnormal(self):
2719 Decimal = self.decimal.Decimal
2720 Context = self.decimal.Context
2721
2722 c = Context()
2723 d = c.is_subnormal(Decimal(10))
2724 self.assertEqual(c.is_subnormal(10), d)
2725 self.assertRaises(TypeError, c.is_subnormal, '10')
2726
2727 def test_is_zero(self):
2728 Decimal = self.decimal.Decimal
2729 Context = self.decimal.Context
2730
2731 c = Context()
2732 d = c.is_zero(Decimal(10))
2733 self.assertEqual(c.is_zero(10), d)
2734 self.assertRaises(TypeError, c.is_zero, '10')
2735
2736 def test_ln(self):
2737 Decimal = self.decimal.Decimal
2738 Context = self.decimal.Context
2739
2740 c = Context()
2741 d = c.ln(Decimal(10))
2742 self.assertEqual(c.ln(10), d)
2743 self.assertRaises(TypeError, c.ln, '10')
2744
2745 def test_log10(self):
2746 Decimal = self.decimal.Decimal
2747 Context = self.decimal.Context
2748
2749 c = Context()
2750 d = c.log10(Decimal(10))
2751 self.assertEqual(c.log10(10), d)
2752 self.assertRaises(TypeError, c.log10, '10')
2753
2754 def test_logb(self):
2755 Decimal = self.decimal.Decimal
2756 Context = self.decimal.Context
2757
2758 c = Context()
2759 d = c.logb(Decimal(10))
2760 self.assertEqual(c.logb(10), d)
2761 self.assertRaises(TypeError, c.logb, '10')
2762
2763 def test_logical_and(self):
2764 Decimal = self.decimal.Decimal
2765 Context = self.decimal.Context
2766
2767 c = Context()
2768 d = c.logical_and(Decimal(1), Decimal(1))
2769 self.assertEqual(c.logical_and(1, 1), d)
2770 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2771 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2772 self.assertRaises(TypeError, c.logical_and, '1', 1)
2773 self.assertRaises(TypeError, c.logical_and, 1, '1')
2774
2775 def test_logical_invert(self):
2776 Decimal = self.decimal.Decimal
2777 Context = self.decimal.Context
2778
2779 c = Context()
2780 d = c.logical_invert(Decimal(1000))
2781 self.assertEqual(c.logical_invert(1000), d)
2782 self.assertRaises(TypeError, c.logical_invert, '1000')
2783
2784 def test_logical_or(self):
2785 Decimal = self.decimal.Decimal
2786 Context = self.decimal.Context
2787
2788 c = Context()
2789 d = c.logical_or(Decimal(1), Decimal(1))
2790 self.assertEqual(c.logical_or(1, 1), d)
2791 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2792 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2793 self.assertRaises(TypeError, c.logical_or, '1', 1)
2794 self.assertRaises(TypeError, c.logical_or, 1, '1')
2795
2796 def test_logical_xor(self):
2797 Decimal = self.decimal.Decimal
2798 Context = self.decimal.Context
2799
2800 c = Context()
2801 d = c.logical_xor(Decimal(1), Decimal(1))
2802 self.assertEqual(c.logical_xor(1, 1), d)
2803 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2804 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2805 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2806 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2807
2808 def test_max(self):
2809 Decimal = self.decimal.Decimal
2810 Context = self.decimal.Context
2811
2812 c = Context()
2813 d = c.max(Decimal(1), Decimal(2))
2814 self.assertEqual(c.max(1, 2), d)
2815 self.assertEqual(c.max(Decimal(1), 2), d)
2816 self.assertEqual(c.max(1, Decimal(2)), d)
2817 self.assertRaises(TypeError, c.max, '1', 2)
2818 self.assertRaises(TypeError, c.max, 1, '2')
2819
2820 def test_max_mag(self):
2821 Decimal = self.decimal.Decimal
2822 Context = self.decimal.Context
2823
2824 c = Context()
2825 d = c.max_mag(Decimal(1), Decimal(2))
2826 self.assertEqual(c.max_mag(1, 2), d)
2827 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2828 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2829 self.assertRaises(TypeError, c.max_mag, '1', 2)
2830 self.assertRaises(TypeError, c.max_mag, 1, '2')
2831
2832 def test_min(self):
2833 Decimal = self.decimal.Decimal
2834 Context = self.decimal.Context
2835
2836 c = Context()
2837 d = c.min(Decimal(1), Decimal(2))
2838 self.assertEqual(c.min(1, 2), d)
2839 self.assertEqual(c.min(Decimal(1), 2), d)
2840 self.assertEqual(c.min(1, Decimal(2)), d)
2841 self.assertRaises(TypeError, c.min, '1', 2)
2842 self.assertRaises(TypeError, c.min, 1, '2')
2843
2844 def test_min_mag(self):
2845 Decimal = self.decimal.Decimal
2846 Context = self.decimal.Context
2847
2848 c = Context()
2849 d = c.min_mag(Decimal(1), Decimal(2))
2850 self.assertEqual(c.min_mag(1, 2), d)
2851 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2852 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2853 self.assertRaises(TypeError, c.min_mag, '1', 2)
2854 self.assertRaises(TypeError, c.min_mag, 1, '2')
2855
2856 def test_minus(self):
2857 Decimal = self.decimal.Decimal
2858 Context = self.decimal.Context
2859
2860 c = Context()
2861 d = c.minus(Decimal(10))
2862 self.assertEqual(c.minus(10), d)
2863 self.assertRaises(TypeError, c.minus, '10')
2864
2865 def test_multiply(self):
2866 Decimal = self.decimal.Decimal
2867 Context = self.decimal.Context
2868
2869 c = Context()
2870 d = c.multiply(Decimal(1), Decimal(2))
2871 self.assertEqual(c.multiply(1, 2), d)
2872 self.assertEqual(c.multiply(Decimal(1), 2), d)
2873 self.assertEqual(c.multiply(1, Decimal(2)), d)
2874 self.assertRaises(TypeError, c.multiply, '1', 2)
2875 self.assertRaises(TypeError, c.multiply, 1, '2')
2876
2877 def test_next_minus(self):
2878 Decimal = self.decimal.Decimal
2879 Context = self.decimal.Context
2880
2881 c = Context()
2882 d = c.next_minus(Decimal(10))
2883 self.assertEqual(c.next_minus(10), d)
2884 self.assertRaises(TypeError, c.next_minus, '10')
2885
2886 def test_next_plus(self):
2887 Decimal = self.decimal.Decimal
2888 Context = self.decimal.Context
2889
2890 c = Context()
2891 d = c.next_plus(Decimal(10))
2892 self.assertEqual(c.next_plus(10), d)
2893 self.assertRaises(TypeError, c.next_plus, '10')
2894
2895 def test_next_toward(self):
2896 Decimal = self.decimal.Decimal
2897 Context = self.decimal.Context
2898
2899 c = Context()
2900 d = c.next_toward(Decimal(1), Decimal(2))
2901 self.assertEqual(c.next_toward(1, 2), d)
2902 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2903 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2904 self.assertRaises(TypeError, c.next_toward, '1', 2)
2905 self.assertRaises(TypeError, c.next_toward, 1, '2')
2906
2907 def test_normalize(self):
2908 Decimal = self.decimal.Decimal
2909 Context = self.decimal.Context
2910
2911 c = Context()
2912 d = c.normalize(Decimal(10))
2913 self.assertEqual(c.normalize(10), d)
2914 self.assertRaises(TypeError, c.normalize, '10')
2915
2916 def test_number_class(self):
2917 Decimal = self.decimal.Decimal
2918 Context = self.decimal.Context
2919
2920 c = Context()
2921 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2922 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2923 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2924
2925 def test_plus(self):
2926 Decimal = self.decimal.Decimal
2927 Context = self.decimal.Context
2928
2929 c = Context()
2930 d = c.plus(Decimal(10))
2931 self.assertEqual(c.plus(10), d)
2932 self.assertRaises(TypeError, c.plus, '10')
2933
2934 def test_power(self):
2935 Decimal = self.decimal.Decimal
2936 Context = self.decimal.Context
2937
2938 c = Context()
2939 d = c.power(Decimal(1), Decimal(4))
2940 self.assertEqual(c.power(1, 4), d)
2941 self.assertEqual(c.power(Decimal(1), 4), d)
2942 self.assertEqual(c.power(1, Decimal(4)), d)
2943 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
2944 self.assertRaises(TypeError, c.power, '1', 4)
2945 self.assertRaises(TypeError, c.power, 1, '4')
2946 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
2947
2948 def test_quantize(self):
2949 Decimal = self.decimal.Decimal
2950 Context = self.decimal.Context
2951
2952 c = Context()
2953 d = c.quantize(Decimal(1), Decimal(2))
2954 self.assertEqual(c.quantize(1, 2), d)
2955 self.assertEqual(c.quantize(Decimal(1), 2), d)
2956 self.assertEqual(c.quantize(1, Decimal(2)), d)
2957 self.assertRaises(TypeError, c.quantize, '1', 2)
2958 self.assertRaises(TypeError, c.quantize, 1, '2')
2959
2960 def test_remainder(self):
2961 Decimal = self.decimal.Decimal
2962 Context = self.decimal.Context
2963
2964 c = Context()
2965 d = c.remainder(Decimal(1), Decimal(2))
2966 self.assertEqual(c.remainder(1, 2), d)
2967 self.assertEqual(c.remainder(Decimal(1), 2), d)
2968 self.assertEqual(c.remainder(1, Decimal(2)), d)
2969 self.assertRaises(TypeError, c.remainder, '1', 2)
2970 self.assertRaises(TypeError, c.remainder, 1, '2')
2971
2972 def test_remainder_near(self):
2973 Decimal = self.decimal.Decimal
2974 Context = self.decimal.Context
2975
2976 c = Context()
2977 d = c.remainder_near(Decimal(1), Decimal(2))
2978 self.assertEqual(c.remainder_near(1, 2), d)
2979 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2980 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2981 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2982 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2983
2984 def test_rotate(self):
2985 Decimal = self.decimal.Decimal
2986 Context = self.decimal.Context
2987
2988 c = Context()
2989 d = c.rotate(Decimal(1), Decimal(2))
2990 self.assertEqual(c.rotate(1, 2), d)
2991 self.assertEqual(c.rotate(Decimal(1), 2), d)
2992 self.assertEqual(c.rotate(1, Decimal(2)), d)
2993 self.assertRaises(TypeError, c.rotate, '1', 2)
2994 self.assertRaises(TypeError, c.rotate, 1, '2')
2995
2996 def test_sqrt(self):
2997 Decimal = self.decimal.Decimal
2998 Context = self.decimal.Context
2999
3000 c = Context()
3001 d = c.sqrt(Decimal(10))
3002 self.assertEqual(c.sqrt(10), d)
3003 self.assertRaises(TypeError, c.sqrt, '10')
3004
3005 def test_same_quantum(self):
3006 Decimal = self.decimal.Decimal
3007 Context = self.decimal.Context
3008
3009 c = Context()
3010 d = c.same_quantum(Decimal(1), Decimal(2))
3011 self.assertEqual(c.same_quantum(1, 2), d)
3012 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3013 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3014 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3015 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3016
3017 def test_scaleb(self):
3018 Decimal = self.decimal.Decimal
3019 Context = self.decimal.Context
3020
3021 c = Context()
3022 d = c.scaleb(Decimal(1), Decimal(2))
3023 self.assertEqual(c.scaleb(1, 2), d)
3024 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3025 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3026 self.assertRaises(TypeError, c.scaleb, '1', 2)
3027 self.assertRaises(TypeError, c.scaleb, 1, '2')
3028
3029 def test_shift(self):
3030 Decimal = self.decimal.Decimal
3031 Context = self.decimal.Context
3032
3033 c = Context()
3034 d = c.shift(Decimal(1), Decimal(2))
3035 self.assertEqual(c.shift(1, 2), d)
3036 self.assertEqual(c.shift(Decimal(1), 2), d)
3037 self.assertEqual(c.shift(1, Decimal(2)), d)
3038 self.assertRaises(TypeError, c.shift, '1', 2)
3039 self.assertRaises(TypeError, c.shift, 1, '2')
3040
3041 def test_subtract(self):
3042 Decimal = self.decimal.Decimal
3043 Context = self.decimal.Context
3044
3045 c = Context()
3046 d = c.subtract(Decimal(1), Decimal(2))
3047 self.assertEqual(c.subtract(1, 2), d)
3048 self.assertEqual(c.subtract(Decimal(1), 2), d)
3049 self.assertEqual(c.subtract(1, Decimal(2)), d)
3050 self.assertRaises(TypeError, c.subtract, '1', 2)
3051 self.assertRaises(TypeError, c.subtract, 1, '2')
3052
3053 def test_to_eng_string(self):
3054 Decimal = self.decimal.Decimal
3055 Context = self.decimal.Context
3056
3057 c = Context()
3058 d = c.to_eng_string(Decimal(10))
3059 self.assertEqual(c.to_eng_string(10), d)
3060 self.assertRaises(TypeError, c.to_eng_string, '10')
3061
3062 def test_to_sci_string(self):
3063 Decimal = self.decimal.Decimal
3064 Context = self.decimal.Context
3065
3066 c = Context()
3067 d = c.to_sci_string(Decimal(10))
3068 self.assertEqual(c.to_sci_string(10), d)
3069 self.assertRaises(TypeError, c.to_sci_string, '10')
3070
3071 def test_to_integral_exact(self):
3072 Decimal = self.decimal.Decimal
3073 Context = self.decimal.Context
3074
3075 c = Context()
3076 d = c.to_integral_exact(Decimal(10))
3077 self.assertEqual(c.to_integral_exact(10), d)
3078 self.assertRaises(TypeError, c.to_integral_exact, '10')
3079
3080 def test_to_integral_value(self):
3081 Decimal = self.decimal.Decimal
3082 Context = self.decimal.Context
3083
3084 c = Context()
3085 d = c.to_integral_value(Decimal(10))
3086 self.assertEqual(c.to_integral_value(10), d)
3087 self.assertRaises(TypeError, c.to_integral_value, '10')
3088 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3089
3090 class CContextAPItests(ContextAPItests):
3091 decimal = C
3092 class PyContextAPItests(ContextAPItests):
3093 decimal = P
3094
3095 class ContextWithStatement(unittest.TestCase):
3096 # Can't do these as docstrings until Python 2.6
3097 # as doctest can't handle __future__ statements
3098
3099 def test_localcontext(self):
3100 # Use a copy of the current context in the block
3101 getcontext = self.decimal.getcontext
3102 localcontext = self.decimal.localcontext
3103
3104 orig_ctx = getcontext()
3105 with localcontext() as enter_ctx:
3106 set_ctx = getcontext()
3107 final_ctx = getcontext()
3108 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3109 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3110 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3111
3112 def test_localcontextarg(self):
3113 # Use a copy of the supplied context in the block
3114 Context = self.decimal.Context
3115 getcontext = self.decimal.getcontext
3116 localcontext = self.decimal.localcontext
3117
3118 localcontext = self.decimal.localcontext
3119 orig_ctx = getcontext()
3120 new_ctx = Context(prec=42)
3121 with localcontext(new_ctx) as enter_ctx:
3122 set_ctx = getcontext()
3123 final_ctx = getcontext()
3124 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3125 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct contex t')
3126 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3127 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3128
3129 def test_nested_with_statements(self):
3130 # Use a copy of the supplied context in the block
3131 Decimal = self.decimal.Decimal
3132 Context = self.decimal.Context
3133 getcontext = self.decimal.getcontext
3134 localcontext = self.decimal.localcontext
3135 Clamped = self.decimal.Clamped
3136 Overflow = self.decimal.Overflow
3137
3138 orig_ctx = getcontext()
3139 orig_ctx.clear_flags()
3140 new_ctx = Context(Emax=384)
3141 with localcontext() as c1:
3142 self.assertEqual(c1.flags, orig_ctx.flags)
3143 self.assertEqual(c1.traps, orig_ctx.traps)
3144 c1.traps[Clamped] = True
3145 c1.Emin = -383
3146 self.assertNotEqual(orig_ctx.Emin, -383)
3147 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3148 self.assertTrue(c1.flags[Clamped])
3149 with localcontext(new_ctx) as c2:
3150 self.assertEqual(c2.flags, new_ctx.flags)
3151 self.assertEqual(c2.traps, new_ctx.traps)
3152 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3153 self.assertFalse(c2.flags[Clamped])
3154 self.assertTrue(c2.flags[Overflow])
3155 del c2
3156 self.assertFalse(c1.flags[Overflow])
3157 del c1
3158 self.assertNotEqual(orig_ctx.Emin, -383)
3159 self.assertFalse(orig_ctx.flags[Clamped])
3160 self.assertFalse(orig_ctx.flags[Overflow])
3161 self.assertFalse(new_ctx.flags[Clamped])
3162 self.assertFalse(new_ctx.flags[Overflow])
3163
3164 def test_with_statements_gc1(self):
3165 localcontext = self.decimal.localcontext
3166
3167 with localcontext() as c1:
3168 del c1
3169 with localcontext() as c2:
3170 del c2
3171 with localcontext() as c3:
3172 del c3
3173 with localcontext() as c4:
3174 del c4
3175
3176 def test_with_statements_gc2(self):
3177 localcontext = self.decimal.localcontext
3178
3179 with localcontext() as c1:
3180 with localcontext(c1) as c2:
3181 del c1
3182 with localcontext(c2) as c3:
3183 del c2
3184 with localcontext(c3) as c4:
3185 del c3
3186 del c4
3187
3188 def test_with_statements_gc3(self):
3189 Context = self.decimal.Context
3190 localcontext = self.decimal.localcontext
3191 getcontext = self.decimal.getcontext
3192 setcontext = self.decimal.setcontext
3193
3194 with localcontext() as c1:
3195 del c1
3196 n1 = Context(prec=1)
3197 setcontext(n1)
3198 with localcontext(n1) as c2:
3199 del n1
3200 self.assertEqual(c2.prec, 1)
3201 del c2
3202 n2 = Context(prec=2)
3203 setcontext(n2)
3204 del n2
3205 self.assertEqual(getcontext().prec, 2)
3206 n3 = Context(prec=3)
3207 setcontext(n3)
3208 self.assertEqual(getcontext().prec, 3)
3209 with localcontext(n3) as c3:
3210 del n3
3211 self.assertEqual(c3.prec, 3)
3212 del c3
3213 n4 = Context(prec=4)
3214 setcontext(n4)
3215 del n4
3216 self.assertEqual(getcontext().prec, 4)
3217 with localcontext() as c4:
3218 self.assertEqual(c4.prec, 4)
3219 del c4
3220
3221 class CContextWithStatement(ContextWithStatement):
3222 decimal = C
3223 class PyContextWithStatement(ContextWithStatement):
3224 decimal = P
3225
3226 class ContextFlags(unittest.TestCase):
3227
3228 def test_flags_irrelevant(self):
3229 # check that the result (numeric result + flags raised) of an
3230 # arithmetic operation doesn't depend on the current flags
3231 Decimal = self.decimal.Decimal
3232 Context = self.decimal.Context
3233 Inexact = self.decimal.Inexact
3234 Rounded = self.decimal.Rounded
3235 Underflow = self.decimal.Underflow
3236 Clamped = self.decimal.Clamped
3237 Subnormal = self.decimal.Subnormal
3238 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
3239
3240 def raise_error(context, flag):
3241 if self.decimal == C:
3242 context.flags[flag] = True
3243 if context.traps[flag]:
3244 raise flag
3245 else:
3246 context._raise_error(flag)
3247
3248 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3249 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3250
3251 # operations that raise various flags, in the form (function, arglist)
3252 operations = [
3253 (context._apply, [Decimal("100E-425000010")]),
3254 (context.sqrt, [Decimal(2)]),
3255 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3256 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3257 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3258 ]
3259
3260 # try various flags individually, then a whole lot at once
3261 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3262 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3263
3264 for fn, args in operations:
3265 # find answer and flags raised using a clean context
3266 context.clear_flags()
3267 ans = fn(*args)
3268 flags = [k for k, v in context.flags.items() if v]
3269
3270 for extra_flags in flagsets:
3271 # set flags, before calling operation
3272 context.clear_flags()
3273 for flag in extra_flags:
3274 raise_error(context, flag)
3275 new_ans = fn(*args)
3276
3277 # flags that we expect to be set after the operation
3278 expected_flags = list(flags)
3279 for flag in extra_flags:
3280 if flag not in expected_flags:
3281 expected_flags.append(flag)
3282 expected_flags.sort(key=id)
3283
3284 # flags we actually got
3285 new_flags = [k for k,v in context.flags.items() if v]
3286 new_flags.sort(key=id)
3287
3288 self.assertEqual(ans, new_ans,
3289 "operation produces different answers depending on flags set: " +
3290 "expected %s, got %s." % (ans, new_ans))
3291 self.assertEqual(new_flags, expected_flags,
3292 "operation raises different flags depending on flags set: " +
3293 "expected %s, got %s" % (expected_flags, new_f lags))
3294
3295 def test_flag_comparisons(self):
3296 Context = self.decimal.Context
3297 Inexact = self.decimal.Inexact
3298 Rounded = self.decimal.Rounded
3299
3300 c = Context()
3301
3302 # Valid SignalDict
3303 self.assertNotEqual(c.flags, c.traps)
3304 self.assertNotEqual(c.traps, c.flags)
3305
3306 c.flags = c.traps
3307 self.assertEqual(c.flags, c.traps)
3308 self.assertEqual(c.traps, c.flags)
3309
3310 c.flags[Rounded] = True
3311 c.traps = c.flags
3312 self.assertEqual(c.flags, c.traps)
3313 self.assertEqual(c.traps, c.flags)
3314
3315 d = {}
3316 d.update(c.flags)
3317 self.assertEqual(d, c.flags)
3318 self.assertEqual(c.flags, d)
3319
3320 d[Inexact] = True
3321 self.assertNotEqual(d, c.flags)
3322 self.assertNotEqual(c.flags, d)
3323
3324 # Invalid SignalDict
3325 d = {Inexact:False}
3326 self.assertNotEqual(d, c.flags)
3327 self.assertNotEqual(c.flags, d)
3328
3329 d = ["xyz"]
3330 self.assertNotEqual(d, c.flags)
3331 self.assertNotEqual(c.flags, d)
3332
3333 class CContextFlags(ContextFlags):
3334 decimal = C
3335 class PyContextFlags(ContextFlags):
3336 decimal = P
3337
3338 class SpecialContexts(unittest.TestCase):
3339 """Test the context templates."""
3340
3341 def test_context_templates(self):
3342 BasicContext = self.decimal.BasicContext
3343 ExtendedContext = self.decimal.ExtendedContext
3344 getcontext = self.decimal.getcontext
3345 setcontext = self.decimal.setcontext
3346 InvalidOperation = self.decimal.InvalidOperation
3347 DivisionByZero = self.decimal.DivisionByZero
3348 Overflow = self.decimal.Overflow
3349 Underflow = self.decimal.Underflow
3350 Clamped = self.decimal.Clamped
3351
3352 assert_signals(self, BasicContext, 'traps',
3353 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3354 )
3355
3356 savecontext = getcontext().copy()
3357 basic_context_prec = BasicContext.prec
3358 extended_context_prec = ExtendedContext.prec
3359
3360 ex = None
3361 try:
3362 BasicContext.prec = ExtendedContext.prec = 441
3363 for template in BasicContext, ExtendedContext:
3364 setcontext(template)
3365 c = getcontext()
3366 self.assertIsNot(c, template)
3367 self.assertEqual(c.prec, 441)
3368 except Exception as e:
3369 ex = e.__class__
3370 finally:
3371 BasicContext.prec = basic_context_prec
3372 ExtendedContext.prec = extended_context_prec
3373 setcontext(savecontext)
3374 if ex:
3375 raise ex
3376
3377 def test_default_context(self):
3378 DefaultContext = self.decimal.DefaultContext
3379 BasicContext = self.decimal.BasicContext
3380 ExtendedContext = self.decimal.ExtendedContext
3381 getcontext = self.decimal.getcontext
3382 setcontext = self.decimal.setcontext
3383 InvalidOperation = self.decimal.InvalidOperation
3384 DivisionByZero = self.decimal.DivisionByZero
3385 Overflow = self.decimal.Overflow
3386
3387 self.assertEqual(BasicContext.prec, 9)
3388 self.assertEqual(ExtendedContext.prec, 9)
3389
3390 assert_signals(self, DefaultContext, 'traps',
3391 [InvalidOperation, DivisionByZero, Overflow]
3392 )
3393
3394 savecontext = getcontext().copy()
3395 default_context_prec = DefaultContext.prec
3396
3397 ex = None
3398 try:
3399 c = getcontext()
3400 saveprec = c.prec
3401
3402 DefaultContext.prec = 961
3403 c = getcontext()
3404 self.assertEqual(c.prec, saveprec)
3405
3406 setcontext(DefaultContext)
3407 c = getcontext()
3408 self.assertIsNot(c, DefaultContext)
3409 self.assertEqual(c.prec, 961)
3410 except Exception as e:
3411 ex = e.__class__
3412 finally:
3413 DefaultContext.prec = default_context_prec
3414 setcontext(savecontext)
3415 if ex:
3416 raise ex
3417
3418 class CSpecialContexts(SpecialContexts):
3419 decimal = C
3420 class PySpecialContexts(SpecialContexts):
3421 decimal = P
3422
3423 class ContextInputValidation(unittest.TestCase):
3424
3425 def test_invalid_context(self):
3426 Context = self.decimal.Context
3427 DefaultContext = self.decimal.DefaultContext
3428
3429 c = DefaultContext.copy()
3430
3431 # prec, Emax
3432 for attr in ['prec', 'Emax']:
3433 setattr(c, attr, 999999)
3434 self.assertEqual(getattr(c, attr), 999999)
3435 self.assertRaises(ValueError, setattr, c, attr, -1)
3436 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3437
3438 # Emin
3439 setattr(c, 'Emin', -999999)
3440 self.assertEqual(getattr(c, 'Emin'), -999999)
3441 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3442 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3443
3444 # rounding: always raise TypeError in order to get consistent
3445 # exceptions across implementations. In decimal, rounding
3446 # modes are strings, in _decimal they are integers. The idea
3447 # is to view rounding as an abstract type and not mind the
3448 # implementation details.
3449 # Hence, a user should view the rounding modes as if they
3450 # had been defined in a language that supports abstract
3451 # data types, e.g. ocaml:
3452 #
3453 # type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;;
3454 #
3455 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3456 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3457 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3458 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3459
3460 # capitals, clamp
3461 for attr in ['capitals', 'clamp']:
3462 self.assertRaises(ValueError, setattr, c, attr, -1)
3463 self.assertRaises(ValueError, setattr, c, attr, 2)
3464 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3465
3466 # Invalid attribute
3467 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3468
3469 # Invalid signal dict
3470 self.assertRaises(TypeError, setattr, c, 'flags', [])
3471 self.assertRaises(KeyError, setattr, c, 'flags', {})
3472 self.assertRaises(KeyError, setattr, c, 'traps',
3473 {'InvalidOperation':0})
3474
3475 # Attributes cannot be deleted
3476 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3477 'flags', 'traps']:
3478 self.assertRaises(AttributeError, c.__delattr__, attr)
3479
3480 # Invalid attributes
3481 self.assertRaises(TypeError, getattr, c, 9)
3482 self.assertRaises(TypeError, setattr, c, 9)
3483
3484 # Invalid values in constructor
3485 self.assertRaises(TypeError, Context, rounding=999999)
3486 self.assertRaises(TypeError, Context, rounding='xyz')
3487 self.assertRaises(ValueError, Context, clamp=2)
3488 self.assertRaises(ValueError, Context, capitals=-1)
3489 self.assertRaises(KeyError, Context, flags=["P"])
3490 self.assertRaises(KeyError, Context, traps=["Q"])
3491
3492 # Type error in conversion
3493 self.assertRaises(TypeError, Context, flags=(0,1))
3494 self.assertRaises(TypeError, Context, traps=(1,0))
3495
3496 class CContextInputValidation(ContextInputValidation):
3497 decimal = C
3498 class PyContextInputValidation(ContextInputValidation):
3499 decimal = P
3500
3501 class CheckAttributes(unittest.TestCase):
3502
3503 def test_module_attributes(self):
3504
3505 # Architecture dependent context limits
3506 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
3507 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
3508 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
3509 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
3510
3511 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
3512 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
3513
3514 self.assertEqual(C.__version__, P.__version__)
3515
3516 x = dir(C)
3517 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
3518 self.assertEqual(set(x) - set(y), {'MallocError', 'FloatOperation'})
3519
3520 def test_context_attributes(self):
3521
3522 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
3523 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
3524 self.assertEqual(set(x) - set(y), set())
3525
3526 def test_decimal_attributes(self):
3527
3528 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3529 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3530 self.assertEqual(set(x) - set(y), set())
3531
3532 class Coverage(unittest.TestCase):
3533
3534 def test_adjusted(self):
3535 Decimal = self.decimal.Decimal
3536
3537 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
3538 # XXX raise?
3539 self.assertEqual(Decimal('nan').adjusted(), 0)
3540 self.assertEqual(Decimal('inf').adjusted(), 0)
3541
3542 def test_canonical(self):
3543 Decimal = self.decimal.Decimal
3544 getcontext = self.decimal.getcontext
3545
3546 x = Decimal(9).canonical()
3547 self.assertEqual(x, 9)
3548
3549 c = getcontext()
3550 x = c.canonical(Decimal(9))
3551 self.assertEqual(x, 9)
3552
3553 def test_context_repr(self):
3554 c = self.decimal.DefaultContext.copy()
3555
3556 c.prec = 425000000
3557 c.Emax = 425000000
3558 c.Emin = -425000000
3559 c.rounding = self.decimal.ROUND_HALF_DOWN
3560 c.capitals = 0
3561 c.clamp = 1
3562 for sig in OrderedSignals[self.decimal]:
3563 c.flags[sig] = False
3564 c.traps[sig] = False
3565
3566 s = c.__repr__()
3567 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
3568 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
3569 "flags=[], traps=[])"
3570 self.assertEqual(s, t)
3571
3572 def test_implicit_context(self):
3573 Decimal = self.decimal.Decimal
3574 localcontext = self.decimal.localcontext
3575
3576 with localcontext() as c:
3577 c.prec = 1
3578 c.Emax = 1
3579 c.Emin = -1
3580
3581 # abs
3582 self.assertEqual(abs(Decimal("-10")), 10)
3583 # add
3584 self.assertEqual(Decimal("7") + 1, 8)
3585 # divide
3586 self.assertEqual(Decimal("10") / 5, 2)
3587 # divide_int
3588 self.assertEqual(Decimal("10") // 7, 1)
3589 # fma
3590 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
3591 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
3592 # three arg power
3593 self.assertEqual(pow(Decimal(10), 2, 7), 2)
3594 # exp
3595 self.assertEqual(Decimal("1.01").exp(), 3)
3596 # is_normal
3597 self.assertIs(Decimal("0.01").is_normal(), False)
3598 # is_subnormal
3599 self.assertIs(Decimal("0.01").is_subnormal(), True)
3600 # ln
3601 self.assertEqual(Decimal("20").ln(), 3)
3602 # log10
3603 self.assertEqual(Decimal("20").log10(), 1)
3604 # logb
3605 self.assertEqual(Decimal("580").logb(), 2)
3606 # logical_invert
3607 self.assertEqual(Decimal("10").logical_invert(), 1)
3608 # minus
3609 self.assertEqual(-Decimal("-10"), 10)
3610 # multiply
3611 self.assertEqual(Decimal("2") * 4, 8)
3612 # next_minus
3613 self.assertEqual(Decimal("10").next_minus(), 9)
3614 # next_plus
3615 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
3616 # normalize
3617 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
3618 # number_class
3619 self.assertEqual(Decimal("10").number_class(), '+Normal')
3620 # plus
3621 self.assertEqual(+Decimal("-1"), -1)
3622 # remainder
3623 self.assertEqual(Decimal("10") % 7, 3)
3624 # subtract
3625 self.assertEqual(Decimal("10") - 7, 3)
3626 # to_integral_exact
3627 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
3628
3629 # Boolean functions
3630 self.assertTrue(Decimal("1").is_canonical())
3631 self.assertTrue(Decimal("1").is_finite())
3632 self.assertTrue(Decimal("1").is_finite())
3633 self.assertTrue(Decimal("snan").is_snan())
3634 self.assertTrue(Decimal("-1").is_signed())
3635 self.assertTrue(Decimal("0").is_zero())
3636 self.assertTrue(Decimal("0").is_zero())
3637
3638 # Copy
3639 with localcontext() as c:
3640 c.prec = 10000
3641 x = 1228 ** 1523
3642 y = -Decimal(x)
3643
3644 z = y.copy_abs()
3645 self.assertEqual(z, x)
3646
3647 z = y.copy_negate()
3648 self.assertEqual(z, x)
3649
3650 z = y.copy_sign(Decimal(1))
3651 self.assertEqual(z, x)
3652
3653 def test_divmod(self):
3654 Decimal = self.decimal.Decimal
3655 localcontext = self.decimal.localcontext
3656 InvalidOperation = self.decimal.InvalidOperation
3657 DivisionByZero = self.decimal.DivisionByZero
3658
3659 with localcontext() as c:
3660 q, r = divmod(Decimal("10912837129"), 1001)
3661 self.assertEqual(q, Decimal('10901935'))
3662 self.assertEqual(r, Decimal('194'))
3663
3664 q, r = divmod(Decimal("NaN"), 7)
3665 self.assertTrue(q.is_nan() and r.is_nan())
3666
3667 c.traps[InvalidOperation] = False
3668 q, r = divmod(Decimal("NaN"), 7)
3669 self.assertTrue(q.is_nan() and r.is_nan())
3670
3671 c.traps[InvalidOperation] = False
3672 c.clear_flags()
3673 q, r = divmod(Decimal("inf"), Decimal("inf"))
3674 self.assertTrue(q.is_nan() and r.is_nan())
3675 self.assertTrue(c.flags[InvalidOperation])
3676
3677 c.clear_flags()
3678 q, r = divmod(Decimal("inf"), 101)
3679 self.assertTrue(q.is_infinite() and r.is_nan())
3680 self.assertTrue(c.flags[InvalidOperation])
3681
3682 c.clear_flags()
3683 q, r = divmod(Decimal(0), 0)
3684 self.assertTrue(q.is_nan() and r.is_nan())
3685 self.assertTrue(c.flags[InvalidOperation])
3686
3687 c.traps[DivisionByZero] = False
3688 c.clear_flags()
3689 q, r = divmod(Decimal(11), 0)
3690 self.assertTrue(q.is_infinite() and r.is_nan())
3691 self.assertTrue(c.flags[InvalidOperation] and
3692 c.flags[DivisionByZero])
3693
3694 def test_power(self):
3695 Decimal = self.decimal.Decimal
3696 localcontext = self.decimal.localcontext
3697 Overflow = self.decimal.Overflow
3698 Rounded = self.decimal.Rounded
3699
3700 with localcontext() as c:
3701 c.prec = 3
3702 c.clear_flags()
3703 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
3704 self.assertTrue(c.flags[Rounded])
3705
3706 c.prec = 1
3707 c.Emax = 1
3708 c.Emin = -1
3709 c.clear_flags()
3710 c.traps[Overflow] = False
3711 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
3712 self.assertTrue(c.flags[Overflow])
3713
3714 def test_quantize(self):
3715 Decimal = self.decimal.Decimal
3716 localcontext = self.decimal.localcontext
3717 InvalidOperation = self.decimal.InvalidOperation
3718
3719 with localcontext() as c:
3720 c.prec = 1
3721 c.Emax = 1
3722 c.Emin = -1
3723 c.traps[InvalidOperation] = False
3724 x = Decimal(99).quantize(Decimal("1e1"))
3725 self.assertTrue(x.is_nan())
3726
3727 def test_radix(self):
3728 Decimal = self.decimal.Decimal
3729 getcontext = self.decimal.getcontext
3730
3731 c = getcontext()
3732 self.assertEqual(Decimal("1").radix(), 10)
3733 self.assertEqual(c.radix(), 10)
3734
3735 def test_rop(self):
3736 Decimal = self.decimal.Decimal
3737
3738 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
3739 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
3740 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
3741
3742 def test_round(self):
3743 # Python3 behavior: round() returns Decimal
3744 Decimal = self.decimal.Decimal
3745 getcontext = self.decimal.getcontext
3746
3747 c = getcontext()
3748 c.prec = 28
3749
3750 self.assertEqual(str(Decimal("9.99").__round__()), "10")
3751 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
3752 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
3753 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
3754 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
3755
3756 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
3757 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
3758
3759 def test_create_decimal(self):
3760 c = self.decimal.Context()
3761 self.assertRaises(ValueError, c.create_decimal, ["%"])
3762
3763 def test_int(self):
3764 Decimal = self.decimal.Decimal
3765 localcontext = self.decimal.localcontext
3766
3767 with localcontext() as c:
3768 c.prec = 9999
3769 x = Decimal(1221**1271) / 10**3923
3770 self.assertEqual(int(x), 1)
3771 self.assertEqual(x.to_integral(), 2)
3772
3773 def test_copy(self):
3774 Context = self.decimal.Context
3775
3776 c = Context()
3777 c.prec = 10000
3778 x = -(1172 ** 1712)
3779
3780 y = c.copy_abs(x)
3781 self.assertEqual(y, -x)
3782
3783 y = c.copy_negate(x)
3784 self.assertEqual(y, -x)
3785
3786 y = c.copy_sign(x, 1)
3787 self.assertEqual(y, -x)
3788
3789 class CCoverage(Coverage):
3790 decimal = C
3791 class PyCoverage(Coverage):
3792 decimal = P
3793
3794 class PyFunctionality(unittest.TestCase):
3795 """Extra functionality in decimal.py"""
3796
3797 def test_py_quantize_watchexp(self):
3798 # watchexp functionality
3799 Decimal = P.Decimal
3800 localcontext = P.localcontext
3801
3802 with localcontext() as c:
3803 c.prec = 1
3804 c.Emax = 1
3805 c.Emin = -1
3806 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
3807 self.assertEqual(x, Decimal('1.00E+5'))
3808
3809 def test_py_alternate_formatting(self):
3810 # triples giving a format, a Decimal, and the expected result
3811 Decimal = P.Decimal
3812 localcontext = P.localcontext
3813
3814 test_values = [
3815 # Issue 7094: Alternate formatting (specified by #)
3816 ('.0e', '1.0', '1e+0'),
3817 ('#.0e', '1.0', '1.e+0'),
3818 ('.0f', '1.0', '1'),
3819 ('#.0f', '1.0', '1.'),
3820 ('g', '1.1', '1.1'),
3821 ('#g', '1.1', '1.1'),
3822 ('.0g', '1', '1'),
3823 ('#.0g', '1', '1.'),
3824 ('.0%', '1.0', '100%'),
3825 ('#.0%', '1.0', '100.%'),
3826 ]
3827 for fmt, d, result in test_values:
3828 self.assertEqual(format(Decimal(d), fmt), result)
3829
3830 class PyWhitebox(unittest.TestCase):
3831 """White box testing for decimal.py"""
3832
3833 def test_py_exact_power(self):
3834 # Rarely exercised lines in _power_exact.
3835 Decimal = P.Decimal
3836 localcontext = P.localcontext
3837
3838 with localcontext() as c:
3839 c.prec = 8
3840 x = Decimal(2**16) ** Decimal("-0.5")
3841 self.assertEqual(x, Decimal('0.00390625'))
3842
3843 x = Decimal(2**16) ** Decimal("-0.6")
3844 self.assertEqual(x, Decimal('0.0012885819'))
3845
3846 x = Decimal("256e7") ** Decimal("-0.5")
3847
3848 x = Decimal(152587890625) ** Decimal('-0.0625')
3849 self.assertEqual(x, Decimal("0.2"))
3850
3851 x = Decimal("152587890625e7") ** Decimal('-0.0625')
3852
3853 x = Decimal(5**2659) ** Decimal('-0.0625')
3854
3855 c.prec = 1
3856 x = Decimal("152587890625") ** Decimal('-0.5')
3857 c.prec = 201
3858 x = Decimal(2**578) ** Decimal("-0.5")
3859
3860 def test_py_immutability_operations(self):
1580 # Do operations and check that it didn't change change internal objects. 3861 # Do operations and check that it didn't change change internal objects.
3862 Decimal = P.Decimal
3863 DefaultContext = P.DefaultContext
3864 setcontext = P.setcontext
3865
3866 c = DefaultContext.copy()
3867 c.traps = dict((s, 0) for s in OrderedSignals[P])
3868 setcontext(c)
1581 3869
1582 d1 = Decimal('-25e55') 3870 d1 = Decimal('-25e55')
1583 b1 = Decimal('-25e55') 3871 b1 = Decimal('-25e55')
1584 d2 = Decimal('33e+33') 3872 d2 = Decimal('33e+33')
1585 b2 = Decimal('33e+33') 3873 b2 = Decimal('33e+33')
1586 3874
1587 def checkSameDec(operation, useOther=False): 3875 def checkSameDec(operation, useOther=False):
1588 if useOther: 3876 if useOther:
1589 eval("d1." + operation + "(d2)") 3877 eval("d1." + operation + "(d2)")
1590 self.assertEqual(d1._sign, b1._sign) 3878 self.assertEqual(d1._sign, b1._sign)
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1642 checkSameDec("max", True) 3930 checkSameDec("max", True)
1643 checkSameDec("min", True) 3931 checkSameDec("min", True)
1644 checkSameDec("normalize") 3932 checkSameDec("normalize")
1645 checkSameDec("quantize", True) 3933 checkSameDec("quantize", True)
1646 checkSameDec("remainder_near", True) 3934 checkSameDec("remainder_near", True)
1647 checkSameDec("same_quantum", True) 3935 checkSameDec("same_quantum", True)
1648 checkSameDec("sqrt") 3936 checkSameDec("sqrt")
1649 checkSameDec("to_eng_string") 3937 checkSameDec("to_eng_string")
1650 checkSameDec("to_integral") 3938 checkSameDec("to_integral")
1651 3939
1652 def test_subclassing(self): 3940 def test_py_decimal_id(self):
1653 # Different behaviours when subclassing Decimal 3941 Decimal = P.Decimal
1654 3942
1655 class MyDecimal(Decimal): 3943 d = Decimal(45)
1656 pass 3944 e = Decimal(d)
1657 3945 self.assertEqual(str(e), '45')
1658 d1 = MyDecimal(1) 3946 self.assertNotEqual(id(d), id(e))
1659 d2 = MyDecimal(2) 3947
1660 d = d1 + d2 3948 def test_py_rescale(self):
1661 self.assertIs(type(d), Decimal) 3949 # Coverage
1662 3950 Decimal = P.Decimal
1663 d = d1.max(d2) 3951 ROUND_UP = P.ROUND_UP
1664 self.assertIs(type(d), Decimal) 3952 localcontext = P.localcontext
1665 3953
1666 def test_implicit_context(self): 3954 with localcontext() as c:
1667 # Check results when context given implicitly. (Issue 2478) 3955 x = Decimal("NaN")._rescale(3, ROUND_UP)
1668 c = getcontext() 3956 self.assertTrue(x.is_nan())
1669 self.assertEqual(str(Decimal(0).sqrt()), 3957
1670 str(c.sqrt(Decimal(0)))) 3958 def test_py__round(self):
1671 3959 # Coverage
1672 def test_conversions_from_int(self): 3960 Decimal = P.Decimal
1673 # Check that methods taking a second Decimal argument will 3961 ROUND_UP = P.ROUND_UP
1674 # always accept an integer in place of a Decimal. 3962
1675 self.assertEqual(Decimal(4).compare(3), 3963 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
1676 Decimal(4).compare(Decimal(3))) 3964
1677 self.assertEqual(Decimal(4).compare_signal(3), 3965 class CFunctionality(unittest.TestCase):
1678 Decimal(4).compare_signal(Decimal(3))) 3966 """Extra functionality in _decimal"""
1679 self.assertEqual(Decimal(4).compare_total(3), 3967
1680 Decimal(4).compare_total(Decimal(3))) 3968 @requires_extra_functionality
1681 self.assertEqual(Decimal(4).compare_total_mag(3), 3969 def test_c_ieee_context(self):
1682 Decimal(4).compare_total_mag(Decimal(3))) 3970 # issue 8786: Add support for IEEE 754 contexts to decimal module.
1683 self.assertEqual(Decimal(10101).logical_and(1001), 3971 IEEEContext = C.IEEEContext
1684 Decimal(10101).logical_and(Decimal(1001))) 3972 DECIMAL32 = C.DECIMAL32
1685 self.assertEqual(Decimal(10101).logical_or(1001), 3973 DECIMAL64 = C.DECIMAL64
1686 Decimal(10101).logical_or(Decimal(1001))) 3974 DECIMAL128 = C.DECIMAL128
1687 self.assertEqual(Decimal(10101).logical_xor(1001), 3975
1688 Decimal(10101).logical_xor(Decimal(1001))) 3976 def assert_rest(self, context):
1689 self.assertEqual(Decimal(567).max(123), 3977 self.assertEqual(context.clamp, 1)
1690 Decimal(567).max(Decimal(123))) 3978 assert_signals(self, context, 'traps', [])
1691 self.assertEqual(Decimal(567).max_mag(123), 3979 assert_signals(self, context, 'flags', [])
1692 Decimal(567).max_mag(Decimal(123))) 3980
1693 self.assertEqual(Decimal(567).min(123), 3981 c = IEEEContext(DECIMAL32)
1694 Decimal(567).min(Decimal(123))) 3982 self.assertEqual(c.prec, 7)
1695 self.assertEqual(Decimal(567).min_mag(123), 3983 self.assertEqual(c.Emax, 96)
1696 Decimal(567).min_mag(Decimal(123))) 3984 self.assertEqual(c.Emin, -95)
1697 self.assertEqual(Decimal(567).next_toward(123), 3985 assert_rest(self, c)
1698 Decimal(567).next_toward(Decimal(123))) 3986
1699 self.assertEqual(Decimal(1234).quantize(100), 3987 c = IEEEContext(DECIMAL64)
1700 Decimal(1234).quantize(Decimal(100))) 3988 self.assertEqual(c.prec, 16)
1701 self.assertEqual(Decimal(768).remainder_near(1234), 3989 self.assertEqual(c.Emax, 384)
1702 Decimal(768).remainder_near(Decimal(1234))) 3990 self.assertEqual(c.Emin, -383)
1703 self.assertEqual(Decimal(123).rotate(1), 3991 assert_rest(self, c)
1704 Decimal(123).rotate(Decimal(1))) 3992
1705 self.assertEqual(Decimal(1234).same_quantum(1000), 3993 c = IEEEContext(DECIMAL128)
1706 Decimal(1234).same_quantum(Decimal(1000))) 3994 self.assertEqual(c.prec, 34)
1707 self.assertEqual(Decimal('9.123').scaleb(-100), 3995 self.assertEqual(c.Emax, 6144)
1708 Decimal('9.123').scaleb(Decimal(-100))) 3996 self.assertEqual(c.Emin, -6143)
1709 self.assertEqual(Decimal(456).shift(-1), 3997 assert_rest(self, c)
1710 Decimal(456).shift(Decimal(-1))) 3998
1711 3999 # Invalid values
1712 self.assertEqual(Decimal(-12).fma(Decimal(45), 67), 4000 self.assertRaises(OverflowError, IEEEContext, 2**63)
1713 Decimal(-12).fma(Decimal(45), Decimal(67))) 4001 self.assertRaises(ValueError, IEEEContext, -1)
1714 self.assertEqual(Decimal(-12).fma(45, 67), 4002 self.assertRaises(ValueError, IEEEContext, 1024)
1715 Decimal(-12).fma(Decimal(45), Decimal(67))) 4003
1716 self.assertEqual(Decimal(-12).fma(45, Decimal(67)), 4004 @requires_IEEE_754
1717 Decimal(-12).fma(Decimal(45), Decimal(67))) 4005 def test_c_float_operation(self):
1718 4006 Decimal = C.Decimal
1719 4007 FloatOperation= C.FloatOperation
1720 class DecimalPythonAPItests(unittest.TestCase): 4008 localcontext = C.localcontext
1721 4009
1722 def test_abc(self): 4010 with localcontext() as c:
1723 self.assertTrue(issubclass(Decimal, numbers.Number)) 4011 c.clear_flags()
1724 self.assertFalse(issubclass(Decimal, numbers.Real)) 4012 self.assertEqual(Decimal(7.5), 7.5)
1725 self.assertIsInstance(Decimal(0), numbers.Number) 4013 self.assertTrue(c.flags[FloatOperation])
1726 self.assertNotIsInstance(Decimal(0), numbers.Real) 4014
1727 4015 c.clear_flags()
1728 def test_pickle(self): 4016 c.traps[FloatOperation] = True
1729 d = Decimal('-3.141590000') 4017 self.assertRaises(FloatOperation, Decimal, 7.5)
1730 p = pickle.dumps(d) 4018 self.assertTrue(c.flags[FloatOperation])
1731 e = pickle.loads(p) 4019
1732 self.assertEqual(d, e) 4020 c.clear_flags()
1733 4021 c.traps[FloatOperation] = False
1734 def test_int(self): 4022 self.assertEqual(c.create_decimal(7.5), 7.5)
1735 for x in range(-250, 250): 4023 self.assertTrue(c.flags[FloatOperation])
1736 s = '%0.2f' % (x / 100.0) 4024
1737 # should work the same as for floats 4025 c.clear_flags()
1738 self.assertEqual(int(Decimal(s)), int(float(s))) 4026 c.traps[FloatOperation] = True
1739 # should work the same as to_integral in the ROUND_DOWN mode 4027 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
1740 d = Decimal(s) 4028 self.assertTrue(c.flags[FloatOperation])
1741 r = d.to_integral(ROUND_DOWN) 4029 c.traps[FloatOperation] = False
1742 self.assertEqual(Decimal(int(d)), r) 4030
1743 4031 def test_c_float_comparison(self):
1744 self.assertRaises(ValueError, int, Decimal('-nan')) 4032 Decimal = C.Decimal
1745 self.assertRaises(ValueError, int, Decimal('snan')) 4033 Context = C.Context
1746 self.assertRaises(OverflowError, int, Decimal('inf')) 4034 FloatOperation= C.FloatOperation
1747 self.assertRaises(OverflowError, int, Decimal('-inf')) 4035 localcontext = C.localcontext
1748 4036
1749 def test_trunc(self): 4037 def assert_attr(a, b, attr, context, signal=None):
1750 for x in range(-250, 250): 4038 context.clear_flags()
1751 s = '%0.2f' % (x / 100.0) 4039 f = getattr(a, attr)
1752 # should work the same as for floats 4040 if signal == FloatOperation:
1753 self.assertEqual(int(Decimal(s)), int(float(s))) 4041 self.assertRaises(signal, f, b)
1754 # should work the same as to_integral in the ROUND_DOWN mode 4042 else:
1755 d = Decimal(s) 4043 self.assertIs(f(b), True)
1756 r = d.to_integral(ROUND_DOWN) 4044 self.assertTrue(context.flags[FloatOperation])
1757 self.assertEqual(Decimal(math.trunc(d)), r) 4045
1758 4046 small_d = Decimal('0.25')
1759 def test_from_float(self): 4047 big_d = Decimal('3.0')
1760 4048 small_f = 0.25
1761 class MyDecimal(Decimal): 4049 big_f = 3.0
1762 pass 4050
1763 4051 zero_d = Decimal('0.0')
1764 r = MyDecimal.from_float(0.1) 4052 neg_zero_d = Decimal('-0.0')
1765 self.assertEqual(type(r), MyDecimal) 4053 zero_f = 0.0
1766 self.assertEqual(str(r), 4054 neg_zero_f = -0.0
1767 '0.1000000000000000055511151231257827021181583404541015625') 4055
1768 bigint = 12345678901234567890123456789 4056 inf_d = Decimal('Infinity')
1769 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint)) 4057 neg_inf_d = Decimal('-Infinity')
1770 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan()) 4058 inf_f = float('inf')
1771 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite()) 4059 neg_inf_f = float('-inf')
1772 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite()) 4060
1773 self.assertEqual(str(MyDecimal.from_float(float('nan'))), 4061 def doit(c, signal=None):
1774 str(Decimal('NaN'))) 4062 # Order
1775 self.assertEqual(str(MyDecimal.from_float(float('inf'))), 4063 for attr in '__lt__', '__le__':
1776 str(Decimal('Infinity'))) 4064 assert_attr(small_d, big_f, attr, c, signal)
1777 self.assertEqual(str(MyDecimal.from_float(float('-inf'))), 4065
1778 str(Decimal('-Infinity'))) 4066 for attr in '__gt__', '__ge__':
1779 self.assertRaises(TypeError, MyDecimal.from_float, 'abc') 4067 assert_attr(big_d, small_f, attr, c, signal)
1780 for i in range(200): 4068
1781 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0) 4069 # Equality
1782 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip 4070 assert_attr(small_d, small_f, '__eq__', c, None)
1783 4071
1784 def test_create_decimal_from_float(self): 4072 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
1785 context = Context(prec=5, rounding=ROUND_DOWN) 4073 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
4074
4075 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
4076 assert_attr(zero_d, zero_f, '__eq__', c, None)
4077
4078 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
4079 assert_attr(inf_d, inf_f, '__eq__', c, None)
4080
4081 # Inequality
4082 assert_attr(small_d, big_f, '__ne__', c, None)
4083
4084 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
4085
4086 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
4087 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
4088
4089 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
4090
4091 def test_containers(c, signal):
4092 c.clear_flags()
4093 s = set([100.0, Decimal('100.0')])
4094 self.assertEqual(len(s), 1)
4095 self.assertTrue(c.flags[FloatOperation])
4096
4097 c.clear_flags()