OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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() |
|