PageRenderTime 61ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lib-python/2.7/test/test_decimal.py

https://bitbucket.org/dac_io/pypy
Python | 2339 lines | 2025 code | 203 blank | 111 comment | 55 complexity | f3fce8701a36f724ad78ea6edacba085 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. # Copyright (c) 2004 Python Software Foundation.
  2. # All rights reserved.
  3. # Written by Eric Price <eprice at tjhsst.edu>
  4. # and Facundo Batista <facundo at taniquetil.com.ar>
  5. # and Raymond Hettinger <python at rcn.com>
  6. # and Aahz (aahz at pobox.com)
  7. # and Tim Peters
  8. """
  9. These are the test cases for the Decimal module.
  10. There are two groups of tests, Arithmetic and Behaviour. The former test
  11. the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
  12. test the pythonic behaviour according to PEP 327.
  13. Cowlishaw's tests can be downloaded from:
  14. www2.hursley.ibm.com/decimal/dectest.zip
  15. This test module can be called from command line with one parameter (Arithmetic
  16. or Behaviour) to test each part, or without parameter to test both parts. If
  17. you're working through IDLE, you can import this test module and call test_main()
  18. with the corresponding argument.
  19. """
  20. import math
  21. import os, sys
  22. import operator
  23. import pickle, copy
  24. import unittest
  25. from decimal import *
  26. import numbers
  27. from test.test_support import (run_unittest, run_doctest,
  28. is_resource_enabled, check_py3k_warnings)
  29. import random
  30. try:
  31. import threading
  32. except ImportError:
  33. threading = None
  34. # Useful Test Constant
  35. Signals = tuple(getcontext().flags.keys())
  36. # Signals ordered with respect to precedence: when an operation
  37. # produces multiple signals, signals occurring later in the list
  38. # should be handled before those occurring earlier in the list.
  39. OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
  40. Underflow, Overflow, DivisionByZero, InvalidOperation)
  41. # Tests are built around these assumed context defaults.
  42. # test_main() restores the original context.
  43. def init():
  44. global ORIGINAL_CONTEXT
  45. ORIGINAL_CONTEXT = getcontext().copy()
  46. DefaultTestContext = Context(
  47. prec = 9,
  48. rounding = ROUND_HALF_EVEN,
  49. traps = dict.fromkeys(Signals, 0)
  50. )
  51. setcontext(DefaultTestContext)
  52. # decorator for skipping tests on non-IEEE 754 platforms
  53. requires_IEEE_754 = unittest.skipUnless(
  54. float.__getformat__("double").startswith("IEEE"),
  55. "test requires IEEE 754 doubles")
  56. TESTDATADIR = 'decimaltestdata'
  57. if __name__ == '__main__':
  58. file = sys.argv[0]
  59. else:
  60. file = __file__
  61. testdir = os.path.dirname(file) or os.curdir
  62. directory = testdir + os.sep + TESTDATADIR + os.sep
  63. skip_expected = not os.path.isdir(directory)
  64. # list of individual .decTest test ids that correspond to tests that
  65. # we're skipping for one reason or another.
  66. skipped_test_ids = set([
  67. # Skip implementation-specific scaleb tests.
  68. 'scbx164',
  69. 'scbx165',
  70. # For some operations (currently exp, ln, log10, power), the decNumber
  71. # reference implementation imposes additional restrictions on the context
  72. # and operands. These restrictions are not part of the specification;
  73. # however, the effect of these restrictions does show up in some of the
  74. # testcases. We skip testcases that violate these restrictions, since
  75. # Decimal behaves differently from decNumber for these testcases so these
  76. # testcases would otherwise fail.
  77. 'expx901',
  78. 'expx902',
  79. 'expx903',
  80. 'expx905',
  81. 'lnx901',
  82. 'lnx902',
  83. 'lnx903',
  84. 'lnx905',
  85. 'logx901',
  86. 'logx902',
  87. 'logx903',
  88. 'logx905',
  89. 'powx1183',
  90. 'powx1184',
  91. 'powx4001',
  92. 'powx4002',
  93. 'powx4003',
  94. 'powx4005',
  95. 'powx4008',
  96. 'powx4010',
  97. 'powx4012',
  98. 'powx4014',
  99. ])
  100. # Make sure it actually raises errors when not expected and caught in flags
  101. # Slower, since it runs some things several times.
  102. EXTENDEDERRORTEST = False
  103. #Map the test cases' error names to the actual errors
  104. ErrorNames = {'clamped' : Clamped,
  105. 'conversion_syntax' : InvalidOperation,
  106. 'division_by_zero' : DivisionByZero,
  107. 'division_impossible' : InvalidOperation,
  108. 'division_undefined' : InvalidOperation,
  109. 'inexact' : Inexact,
  110. 'invalid_context' : InvalidOperation,
  111. 'invalid_operation' : InvalidOperation,
  112. 'overflow' : Overflow,
  113. 'rounded' : Rounded,
  114. 'subnormal' : Subnormal,
  115. 'underflow' : Underflow}
  116. def Nonfunction(*args):
  117. """Doesn't do anything."""
  118. return None
  119. RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
  120. 'down' : ROUND_DOWN,
  121. 'floor' : ROUND_FLOOR,
  122. 'half_down' : ROUND_HALF_DOWN,
  123. 'half_even' : ROUND_HALF_EVEN,
  124. 'half_up' : ROUND_HALF_UP,
  125. 'up' : ROUND_UP,
  126. '05up' : ROUND_05UP}
  127. # Name adapter to be able to change the Decimal and Context
  128. # interface without changing the test files from Cowlishaw
  129. nameAdapter = {'and':'logical_and',
  130. 'apply':'_apply',
  131. 'class':'number_class',
  132. 'comparesig':'compare_signal',
  133. 'comparetotal':'compare_total',
  134. 'comparetotmag':'compare_total_mag',
  135. 'copy':'copy_decimal',
  136. 'copyabs':'copy_abs',
  137. 'copynegate':'copy_negate',
  138. 'copysign':'copy_sign',
  139. 'divideint':'divide_int',
  140. 'invert':'logical_invert',
  141. 'iscanonical':'is_canonical',
  142. 'isfinite':'is_finite',
  143. 'isinfinite':'is_infinite',
  144. 'isnan':'is_nan',
  145. 'isnormal':'is_normal',
  146. 'isqnan':'is_qnan',
  147. 'issigned':'is_signed',
  148. 'issnan':'is_snan',
  149. 'issubnormal':'is_subnormal',
  150. 'iszero':'is_zero',
  151. 'maxmag':'max_mag',
  152. 'minmag':'min_mag',
  153. 'nextminus':'next_minus',
  154. 'nextplus':'next_plus',
  155. 'nexttoward':'next_toward',
  156. 'or':'logical_or',
  157. 'reduce':'normalize',
  158. 'remaindernear':'remainder_near',
  159. 'samequantum':'same_quantum',
  160. 'squareroot':'sqrt',
  161. 'toeng':'to_eng_string',
  162. 'tointegral':'to_integral_value',
  163. 'tointegralx':'to_integral_exact',
  164. 'tosci':'to_sci_string',
  165. 'xor':'logical_xor',
  166. }
  167. # The following functions return True/False rather than a Decimal instance
  168. LOGICAL_FUNCTIONS = (
  169. 'is_canonical',
  170. 'is_finite',
  171. 'is_infinite',
  172. 'is_nan',
  173. 'is_normal',
  174. 'is_qnan',
  175. 'is_signed',
  176. 'is_snan',
  177. 'is_subnormal',
  178. 'is_zero',
  179. 'same_quantum',
  180. )
  181. class DecimalTest(unittest.TestCase):
  182. """Class which tests the Decimal class against the test cases.
  183. Changed for unittest.
  184. """
  185. def setUp(self):
  186. self.context = Context()
  187. self.ignore_list = ['#']
  188. # Basically, a # means return NaN InvalidOperation.
  189. # Different from a sNaN in trim
  190. self.ChangeDict = {'precision' : self.change_precision,
  191. 'rounding' : self.change_rounding_method,
  192. 'maxexponent' : self.change_max_exponent,
  193. 'minexponent' : self.change_min_exponent,
  194. 'clamp' : self.change_clamp}
  195. def eval_file(self, file):
  196. global skip_expected
  197. if skip_expected:
  198. raise unittest.SkipTest
  199. return
  200. with open(file) as f:
  201. for line in f:
  202. line = line.replace('\r\n', '').replace('\n', '')
  203. #print line
  204. try:
  205. t = self.eval_line(line)
  206. except DecimalException as exception:
  207. #Exception raised where there shouldn't have been one.
  208. self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
  209. return
  210. def eval_line(self, s):
  211. if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
  212. s = (s.split('->')[0] + '->' +
  213. s.split('->')[1].split('--')[0]).strip()
  214. else:
  215. s = s.split('--')[0].strip()
  216. for ignore in self.ignore_list:
  217. if s.find(ignore) >= 0:
  218. #print s.split()[0], 'NotImplemented--', ignore
  219. return
  220. if not s:
  221. return
  222. elif ':' in s:
  223. return self.eval_directive(s)
  224. else:
  225. return self.eval_equation(s)
  226. def eval_directive(self, s):
  227. funct, value = map(lambda x: x.strip().lower(), s.split(':'))
  228. if funct == 'rounding':
  229. value = RoundingDict[value]
  230. else:
  231. try:
  232. value = int(value)
  233. except ValueError:
  234. pass
  235. funct = self.ChangeDict.get(funct, Nonfunction)
  236. funct(value)
  237. def eval_equation(self, s):
  238. #global DEFAULT_PRECISION
  239. #print DEFAULT_PRECISION
  240. if not TEST_ALL and random.random() < 0.90:
  241. return
  242. try:
  243. Sides = s.split('->')
  244. L = Sides[0].strip().split()
  245. id = L[0]
  246. if DEBUG:
  247. print "Test ", id,
  248. funct = L[1].lower()
  249. valstemp = L[2:]
  250. L = Sides[1].strip().split()
  251. ans = L[0]
  252. exceptions = L[1:]
  253. except (TypeError, AttributeError, IndexError):
  254. raise InvalidOperation
  255. def FixQuotes(val):
  256. val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
  257. val = val.replace("'", '').replace('"', '')
  258. val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
  259. return val
  260. if id in skipped_test_ids:
  261. return
  262. fname = nameAdapter.get(funct, funct)
  263. if fname == 'rescale':
  264. return
  265. funct = getattr(self.context, fname)
  266. vals = []
  267. conglomerate = ''
  268. quote = 0
  269. theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
  270. for exception in Signals:
  271. self.context.traps[exception] = 1 #Catch these bugs...
  272. for exception in theirexceptions:
  273. self.context.traps[exception] = 0
  274. for i, val in enumerate(valstemp):
  275. if val.count("'") % 2 == 1:
  276. quote = 1 - quote
  277. if quote:
  278. conglomerate = conglomerate + ' ' + val
  279. continue
  280. else:
  281. val = conglomerate + val
  282. conglomerate = ''
  283. v = FixQuotes(val)
  284. if fname in ('to_sci_string', 'to_eng_string'):
  285. if EXTENDEDERRORTEST:
  286. for error in theirexceptions:
  287. self.context.traps[error] = 1
  288. try:
  289. funct(self.context.create_decimal(v))
  290. except error:
  291. pass
  292. except Signals, e:
  293. self.fail("Raised %s in %s when %s disabled" % \
  294. (e, s, error))
  295. else:
  296. self.fail("Did not raise %s in %s" % (error, s))
  297. self.context.traps[error] = 0
  298. v = self.context.create_decimal(v)
  299. else:
  300. v = Decimal(v, self.context)
  301. vals.append(v)
  302. ans = FixQuotes(ans)
  303. if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
  304. for error in theirexceptions:
  305. self.context.traps[error] = 1
  306. try:
  307. funct(*vals)
  308. except error:
  309. pass
  310. except Signals, e:
  311. self.fail("Raised %s in %s when %s disabled" % \
  312. (e, s, error))
  313. else:
  314. self.fail("Did not raise %s in %s" % (error, s))
  315. self.context.traps[error] = 0
  316. # as above, but add traps cumulatively, to check precedence
  317. ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
  318. for error in ordered_errors:
  319. self.context.traps[error] = 1
  320. try:
  321. funct(*vals)
  322. except error:
  323. pass
  324. except Signals, e:
  325. self.fail("Raised %s in %s; expected %s" %
  326. (type(e), s, error))
  327. else:
  328. self.fail("Did not raise %s in %s" % (error, s))
  329. # reset traps
  330. for error in ordered_errors:
  331. self.context.traps[error] = 0
  332. if DEBUG:
  333. print "--", self.context
  334. try:
  335. result = str(funct(*vals))
  336. if fname in LOGICAL_FUNCTIONS:
  337. result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
  338. except Signals, error:
  339. self.fail("Raised %s in %s" % (error, s))
  340. except: #Catch any error long enough to state the test case.
  341. print "ERROR:", s
  342. raise
  343. myexceptions = self.getexceptions()
  344. self.context.clear_flags()
  345. self.assertEqual(result, ans,
  346. 'Incorrect answer for ' + s + ' -- got ' + result)
  347. self.assertItemsEqual(myexceptions, theirexceptions,
  348. 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
  349. return
  350. def getexceptions(self):
  351. return [e for e in Signals if self.context.flags[e]]
  352. def change_precision(self, prec):
  353. self.context.prec = prec
  354. def change_rounding_method(self, rounding):
  355. self.context.rounding = rounding
  356. def change_min_exponent(self, exp):
  357. self.context.Emin = exp
  358. def change_max_exponent(self, exp):
  359. self.context.Emax = exp
  360. def change_clamp(self, clamp):
  361. self.context._clamp = clamp
  362. # The following classes test the behaviour of Decimal according to PEP 327
  363. class DecimalExplicitConstructionTest(unittest.TestCase):
  364. '''Unit tests for Explicit Construction cases of Decimal.'''
  365. def test_explicit_empty(self):
  366. self.assertEqual(Decimal(), Decimal("0"))
  367. def test_explicit_from_None(self):
  368. self.assertRaises(TypeError, Decimal, None)
  369. def test_explicit_from_int(self):
  370. #positive
  371. d = Decimal(45)
  372. self.assertEqual(str(d), '45')
  373. #very large positive
  374. d = Decimal(500000123)
  375. self.assertEqual(str(d), '500000123')
  376. #negative
  377. d = Decimal(-45)
  378. self.assertEqual(str(d), '-45')
  379. #zero
  380. d = Decimal(0)
  381. self.assertEqual(str(d), '0')
  382. def test_explicit_from_string(self):
  383. #empty
  384. self.assertEqual(str(Decimal('')), 'NaN')
  385. #int
  386. self.assertEqual(str(Decimal('45')), '45')
  387. #float
  388. self.assertEqual(str(Decimal('45.34')), '45.34')
  389. #engineer notation
  390. self.assertEqual(str(Decimal('45e2')), '4.5E+3')
  391. #just not a number
  392. self.assertEqual(str(Decimal('ugly')), 'NaN')
  393. #leading and trailing whitespace permitted
  394. self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
  395. self.assertEqual(str(Decimal(' -7.89')), '-7.89')
  396. #unicode strings should be permitted
  397. self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
  398. self.assertEqual(str(Decimal(u'45')), '45')
  399. self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
  400. self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
  401. def test_explicit_from_tuples(self):
  402. #zero
  403. d = Decimal( (0, (0,), 0) )
  404. self.assertEqual(str(d), '0')
  405. #int
  406. d = Decimal( (1, (4, 5), 0) )
  407. self.assertEqual(str(d), '-45')
  408. #float
  409. d = Decimal( (0, (4, 5, 3, 4), -2) )
  410. self.assertEqual(str(d), '45.34')
  411. #weird
  412. d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
  413. self.assertEqual(str(d), '-4.34913534E-17')
  414. #wrong number of items
  415. self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
  416. #bad sign
  417. self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
  418. self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
  419. self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
  420. #bad exp
  421. self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
  422. self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
  423. self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
  424. #bad coefficients
  425. self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
  426. self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
  427. self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
  428. self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
  429. def test_explicit_from_bool(self):
  430. self.assertIs(bool(Decimal(0)), False)
  431. self.assertIs(bool(Decimal(1)), True)
  432. self.assertEqual(Decimal(False), Decimal(0))
  433. self.assertEqual(Decimal(True), Decimal(1))
  434. def test_explicit_from_Decimal(self):
  435. #positive
  436. d = Decimal(45)
  437. e = Decimal(d)
  438. self.assertEqual(str(e), '45')
  439. self.assertNotEqual(id(d), id(e))
  440. #very large positive
  441. d = Decimal(500000123)
  442. e = Decimal(d)
  443. self.assertEqual(str(e), '500000123')
  444. self.assertNotEqual(id(d), id(e))
  445. #negative
  446. d = Decimal(-45)
  447. e = Decimal(d)
  448. self.assertEqual(str(e), '-45')
  449. self.assertNotEqual(id(d), id(e))
  450. #zero
  451. d = Decimal(0)
  452. e = Decimal(d)
  453. self.assertEqual(str(e), '0')
  454. self.assertNotEqual(id(d), id(e))
  455. @requires_IEEE_754
  456. def test_explicit_from_float(self):
  457. r = Decimal(0.1)
  458. self.assertEqual(type(r), Decimal)
  459. self.assertEqual(str(r),
  460. '0.1000000000000000055511151231257827021181583404541015625')
  461. self.assertTrue(Decimal(float('nan')).is_qnan())
  462. self.assertTrue(Decimal(float('inf')).is_infinite())
  463. self.assertTrue(Decimal(float('-inf')).is_infinite())
  464. self.assertEqual(str(Decimal(float('nan'))),
  465. str(Decimal('NaN')))
  466. self.assertEqual(str(Decimal(float('inf'))),
  467. str(Decimal('Infinity')))
  468. self.assertEqual(str(Decimal(float('-inf'))),
  469. str(Decimal('-Infinity')))
  470. self.assertEqual(str(Decimal(float('-0.0'))),
  471. str(Decimal('-0')))
  472. for i in range(200):
  473. x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
  474. self.assertEqual(x, float(Decimal(x))) # roundtrip
  475. def test_explicit_context_create_decimal(self):
  476. nc = copy.copy(getcontext())
  477. nc.prec = 3
  478. # empty
  479. d = Decimal()
  480. self.assertEqual(str(d), '0')
  481. d = nc.create_decimal()
  482. self.assertEqual(str(d), '0')
  483. # from None
  484. self.assertRaises(TypeError, nc.create_decimal, None)
  485. # from int
  486. d = nc.create_decimal(456)
  487. self.assertIsInstance(d, Decimal)
  488. self.assertEqual(nc.create_decimal(45678),
  489. nc.create_decimal('457E+2'))
  490. # from string
  491. d = Decimal('456789')
  492. self.assertEqual(str(d), '456789')
  493. d = nc.create_decimal('456789')
  494. self.assertEqual(str(d), '4.57E+5')
  495. # leading and trailing whitespace should result in a NaN;
  496. # spaces are already checked in Cowlishaw's test-suite, so
  497. # here we just check that a trailing newline results in a NaN
  498. self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
  499. # from tuples
  500. d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
  501. self.assertEqual(str(d), '-4.34913534E-17')
  502. d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
  503. self.assertEqual(str(d), '-4.35E-17')
  504. # from Decimal
  505. prevdec = Decimal(500000123)
  506. d = Decimal(prevdec)
  507. self.assertEqual(str(d), '500000123')
  508. d = nc.create_decimal(prevdec)
  509. self.assertEqual(str(d), '5.00E+8')
  510. def test_unicode_digits(self):
  511. test_values = {
  512. u'\uff11': '1',
  513. u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
  514. u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
  515. }
  516. for input, expected in test_values.items():
  517. self.assertEqual(str(Decimal(input)), expected)
  518. class DecimalImplicitConstructionTest(unittest.TestCase):
  519. '''Unit tests for Implicit Construction cases of Decimal.'''
  520. def test_implicit_from_None(self):
  521. self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
  522. def test_implicit_from_int(self):
  523. #normal
  524. self.assertEqual(str(Decimal(5) + 45), '50')
  525. #exceeding precision
  526. self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
  527. def test_implicit_from_string(self):
  528. self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
  529. def test_implicit_from_float(self):
  530. self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
  531. def test_implicit_from_Decimal(self):
  532. self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
  533. def test_rop(self):
  534. # Allow other classes to be trained to interact with Decimals
  535. class E:
  536. def __divmod__(self, other):
  537. return 'divmod ' + str(other)
  538. def __rdivmod__(self, other):
  539. return str(other) + ' rdivmod'
  540. def __lt__(self, other):
  541. return 'lt ' + str(other)
  542. def __gt__(self, other):
  543. return 'gt ' + str(other)
  544. def __le__(self, other):
  545. return 'le ' + str(other)
  546. def __ge__(self, other):
  547. return 'ge ' + str(other)
  548. def __eq__(self, other):
  549. return 'eq ' + str(other)
  550. def __ne__(self, other):
  551. return 'ne ' + str(other)
  552. self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
  553. self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
  554. self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
  555. self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
  556. self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
  557. self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
  558. self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
  559. self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
  560. # insert operator methods and then exercise them
  561. oplist = [
  562. ('+', '__add__', '__radd__'),
  563. ('-', '__sub__', '__rsub__'),
  564. ('*', '__mul__', '__rmul__'),
  565. ('%', '__mod__', '__rmod__'),
  566. ('//', '__floordiv__', '__rfloordiv__'),
  567. ('**', '__pow__', '__rpow__')
  568. ]
  569. with check_py3k_warnings():
  570. if 1 / 2 == 0:
  571. # testing with classic division, so add __div__
  572. oplist.append(('/', '__div__', '__rdiv__'))
  573. else:
  574. # testing with -Qnew, so add __truediv__
  575. oplist.append(('/', '__truediv__', '__rtruediv__'))
  576. for sym, lop, rop in oplist:
  577. setattr(E, lop, lambda self, other: 'str' + lop + str(other))
  578. setattr(E, rop, lambda self, other: str(other) + rop + 'str')
  579. self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
  580. 'str' + lop + '10')
  581. self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
  582. '10' + rop + 'str')
  583. class DecimalFormatTest(unittest.TestCase):
  584. '''Unit tests for the format function.'''
  585. def test_formatting(self):
  586. # triples giving a format, a Decimal, and the expected result
  587. test_values = [
  588. ('e', '0E-15', '0e-15'),
  589. ('e', '2.3E-15', '2.3e-15'),
  590. ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
  591. ('e', '2.30000E-15', '2.30000e-15'),
  592. ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
  593. ('e', '1.5', '1.5e+0'),
  594. ('e', '0.15', '1.5e-1'),
  595. ('e', '0.015', '1.5e-2'),
  596. ('e', '0.0000000000015', '1.5e-12'),
  597. ('e', '15.0', '1.50e+1'),
  598. ('e', '-15', '-1.5e+1'),
  599. ('e', '0', '0e+0'),
  600. ('e', '0E1', '0e+1'),
  601. ('e', '0.0', '0e-1'),
  602. ('e', '0.00', '0e-2'),
  603. ('.6e', '0E-15', '0.000000e-9'),
  604. ('.6e', '0', '0.000000e+6'),
  605. ('.6e', '9.999999', '9.999999e+0'),
  606. ('.6e', '9.9999999', '1.000000e+1'),
  607. ('.6e', '-1.23e5', '-1.230000e+5'),
  608. ('.6e', '1.23456789e-3', '1.234568e-3'),
  609. ('f', '0', '0'),
  610. ('f', '0.0', '0.0'),
  611. ('f', '0E-2', '0.00'),
  612. ('f', '0.00E-8', '0.0000000000'),
  613. ('f', '0E1', '0'), # loses exponent information
  614. ('f', '3.2E1', '32'),
  615. ('f', '3.2E2', '320'),
  616. ('f', '3.20E2', '320'),
  617. ('f', '3.200E2', '320.0'),
  618. ('f', '3.2E-6', '0.0000032'),
  619. ('.6f', '0E-15', '0.000000'), # all zeros treated equally
  620. ('.6f', '0E1', '0.000000'),
  621. ('.6f', '0', '0.000000'),
  622. ('.0f', '0', '0'), # no decimal point
  623. ('.0f', '0e-2', '0'),
  624. ('.0f', '3.14159265', '3'),
  625. ('.1f', '3.14159265', '3.1'),
  626. ('.4f', '3.14159265', '3.1416'),
  627. ('.6f', '3.14159265', '3.141593'),
  628. ('.7f', '3.14159265', '3.1415926'), # round-half-even!
  629. ('.8f', '3.14159265', '3.14159265'),
  630. ('.9f', '3.14159265', '3.141592650'),
  631. ('g', '0', '0'),
  632. ('g', '0.0', '0.0'),
  633. ('g', '0E1', '0e+1'),
  634. ('G', '0E1', '0E+1'),
  635. ('g', '0E-5', '0.00000'),
  636. ('g', '0E-6', '0.000000'),
  637. ('g', '0E-7', '0e-7'),
  638. ('g', '-0E2', '-0e+2'),
  639. ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
  640. ('.1g', '3.14159265', '3'),
  641. ('.2g', '3.14159265', '3.1'),
  642. ('.5g', '3.14159265', '3.1416'),
  643. ('.7g', '3.14159265', '3.141593'),
  644. ('.8g', '3.14159265', '3.1415926'), # round-half-even!
  645. ('.9g', '3.14159265', '3.14159265'),
  646. ('.10g', '3.14159265', '3.14159265'), # don't pad
  647. ('%', '0E1', '0%'),
  648. ('%', '0E0', '0%'),
  649. ('%', '0E-1', '0%'),
  650. ('%', '0E-2', '0%'),
  651. ('%', '0E-3', '0.0%'),
  652. ('%', '0E-4', '0.00%'),
  653. ('.3%', '0', '0.000%'), # all zeros treated equally
  654. ('.3%', '0E10', '0.000%'),
  655. ('.3%', '0E-10', '0.000%'),
  656. ('.3%', '2.34', '234.000%'),
  657. ('.3%', '1.234567', '123.457%'),
  658. ('.0%', '1.23', '123%'),
  659. ('e', 'NaN', 'NaN'),
  660. ('f', '-NaN123', '-NaN123'),
  661. ('+g', 'NaN456', '+NaN456'),
  662. ('.3e', 'Inf', 'Infinity'),
  663. ('.16f', '-Inf', '-Infinity'),
  664. ('.0g', '-sNaN', '-sNaN'),
  665. ('', '1.00', '1.00'),
  666. # test alignment and padding
  667. ('6', '123', ' 123'),
  668. ('<6', '123', '123 '),
  669. ('>6', '123', ' 123'),
  670. ('^6', '123', ' 123 '),
  671. ('=+6', '123', '+ 123'),
  672. ('#<10', 'NaN', 'NaN#######'),
  673. ('#<10', '-4.3', '-4.3######'),
  674. ('#<+10', '0.0130', '+0.0130###'),
  675. ('#< 10', '0.0130', ' 0.0130###'),
  676. ('@>10', '-Inf', '@-Infinity'),
  677. ('#>5', '-Inf', '-Infinity'),
  678. ('?^5', '123', '?123?'),
  679. ('%^6', '123', '%123%%'),
  680. (' ^6', '-45.6', '-45.6 '),
  681. ('/=10', '-45.6', '-/////45.6'),
  682. ('/=+10', '45.6', '+/////45.6'),
  683. ('/= 10', '45.6', ' /////45.6'),
  684. # thousands separator
  685. (',', '1234567', '1,234,567'),
  686. (',', '123456', '123,456'),
  687. (',', '12345', '12,345'),
  688. (',', '1234', '1,234'),
  689. (',', '123', '123'),
  690. (',', '12', '12'),
  691. (',', '1', '1'),
  692. (',', '0', '0'),
  693. (',', '-1234567', '-1,234,567'),
  694. (',', '-123456', '-123,456'),
  695. ('7,', '123456', '123,456'),
  696. ('8,', '123456', ' 123,456'),
  697. ('08,', '123456', '0,123,456'), # special case: extra 0 needed
  698. ('+08,', '123456', '+123,456'), # but not if there's a sign
  699. (' 08,', '123456', ' 123,456'),
  700. ('08,', '-123456', '-123,456'),
  701. ('+09,', '123456', '+0,123,456'),
  702. # ... with fractional part...
  703. ('07,', '1234.56', '1,234.56'),
  704. ('08,', '1234.56', '1,234.56'),
  705. ('09,', '1234.56', '01,234.56'),
  706. ('010,', '1234.56', '001,234.56'),
  707. ('011,', '1234.56', '0,001,234.56'),
  708. ('012,', '1234.56', '0,001,234.56'),
  709. ('08,.1f', '1234.5', '01,234.5'),
  710. # no thousands separators in fraction part
  711. (',', '1.23456789', '1.23456789'),
  712. (',%', '123.456789', '12,345.6789%'),
  713. (',e', '123456', '1.23456e+5'),
  714. (',E', '123456', '1.23456E+5'),
  715. # issue 6850
  716. ('a=-7.0', '0.12345', 'aaaa0.1'),
  717. ]
  718. for fmt, d, result in test_values:
  719. self.assertEqual(format(Decimal(d), fmt), result)
  720. def test_n_format(self):
  721. try:
  722. from locale import CHAR_MAX
  723. except ImportError:
  724. return
  725. # Set up some localeconv-like dictionaries
  726. en_US = {
  727. 'decimal_point' : '.',
  728. 'grouping' : [3, 3, 0],
  729. 'thousands_sep': ','
  730. }
  731. fr_FR = {
  732. 'decimal_point' : ',',
  733. 'grouping' : [CHAR_MAX],
  734. 'thousands_sep' : ''
  735. }
  736. ru_RU = {
  737. 'decimal_point' : ',',
  738. 'grouping' : [3, 3, 0],
  739. 'thousands_sep' : ' '
  740. }
  741. crazy = {
  742. 'decimal_point' : '&',
  743. 'grouping' : [1, 4, 2, CHAR_MAX],
  744. 'thousands_sep' : '-'
  745. }
  746. def get_fmt(x, locale, fmt='n'):
  747. return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
  748. self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
  749. self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
  750. self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
  751. self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
  752. self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
  753. self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
  754. self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
  755. self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
  756. self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
  757. self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
  758. self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
  759. self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
  760. # zero padding
  761. self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
  762. self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
  763. self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
  764. self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
  765. self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
  766. self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
  767. self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
  768. self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
  769. self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
  770. self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
  771. self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
  772. self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
  773. self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
  774. self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
  775. self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
  776. self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
  777. self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
  778. self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
  779. class DecimalArithmeticOperatorsTest(unittest.TestCase):
  780. '''Unit tests for all arithmetic operators, binary and unary.'''
  781. def test_addition(self):
  782. d1 = Decimal('-11.1')
  783. d2 = Decimal('22.2')
  784. #two Decimals
  785. self.assertEqual(d1+d2, Decimal('11.1'))
  786. self.assertEqual(d2+d1, Decimal('11.1'))
  787. #with other type, left
  788. c = d1 + 5
  789. self.assertEqual(c, Decimal('-6.1'))
  790. self.assertEqual(type(c), type(d1))
  791. #with other type, right
  792. c = 5 + d1
  793. self.assertEqual(c, Decimal('-6.1'))
  794. self.assertEqual(type(c), type(d1))
  795. #inline with decimal
  796. d1 += d2
  797. self.assertEqual(d1, Decimal('11.1'))
  798. #inline with other type
  799. d1 += 5
  800. self.assertEqual(d1, Decimal('16.1'))
  801. def test_subtraction(self):
  802. d1 = Decimal('-11.1')
  803. d2 = Decimal('22.2')
  804. #two Decimals
  805. self.assertEqual(d1-d2, Decimal('-33.3'))
  806. self.assertEqual(d2-d1, Decimal('33.3'))
  807. #with other type, left
  808. c = d1 - 5
  809. self.assertEqual(c, Decimal('-16.1'))
  810. self.assertEqual(type(c), type(d1))
  811. #with other type, right
  812. c = 5 - d1
  813. self.assertEqual(c, Decimal('16.1'))
  814. self.assertEqual(type(c), type(d1))
  815. #inline with decimal
  816. d1 -= d2
  817. self.assertEqual(d1, Decimal('-33.3'))
  818. #inline with other type
  819. d1 -= 5
  820. self.assertEqual(d1, Decimal('-38.3'))
  821. def test_multiplication(self):
  822. d1 = Decimal('-5')
  823. d2 = Decimal('3')
  824. #two Decimals
  825. self.assertEqual(d1*d2, Decimal('-15'))
  826. self.assertEqual(d2*d1, Decimal('-15'))
  827. #with other type, left
  828. c = d1 * 5
  829. self.assertEqual(c, Decimal('-25'))
  830. self.assertEqual(type(c), type(d1))
  831. #with other type, right
  832. c = 5 * d1
  833. self.assertEqual(c, Decimal('-25'))
  834. self.assertEqual(type(c), type(d1))
  835. #inline with decimal
  836. d1 *= d2
  837. self.assertEqual(d1, Decimal('-15'))
  838. #inline with other type
  839. d1 *= 5
  840. self.assertEqual(d1, Decimal('-75'))
  841. def test_division(self):
  842. d1 = Decimal('-5')
  843. d2 = Decimal('2')
  844. #two Decimals
  845. self.assertEqual(d1/d2, Decimal('-2.5'))
  846. self.assertEqual(d2/d1, Decimal('-0.4'))
  847. #with other type, left
  848. c = d1 / 4
  849. self.assertEqual(c, Decimal('-1.25'))
  850. self.assertEqual(type(c), type(d1))
  851. #with other type, right
  852. c = 4 / d1
  853. self.assertEqual(c, Decimal('-0.8'))
  854. self.assertEqual(type(c), type(d1))
  855. #inline with decimal
  856. d1 /= d2
  857. self.assertEqual(d1, Decimal('-2.5'))
  858. #inline with other type
  859. d1 /= 4
  860. self.assertEqual(d1, Decimal('-0.625'))
  861. def test_floor_division(self):
  862. d1 = Decimal('5')
  863. d2 = Decimal('2')
  864. #two Decimals
  865. self.assertEqual(d1//d2, Decimal('2'))
  866. self.assertEqual(d2//d1, Decimal('0'))
  867. #with other type, left
  868. c = d1 // 4
  869. self.assertEqual(c, Decimal('1'))
  870. self.assertEqual(type(c), type(d1))
  871. #with other type, right
  872. c = 7 // d1
  873. self.assertEqual(c, Decimal('1'))
  874. self.assertEqual(type(c), type(d1))
  875. #inline with decimal
  876. d1 //= d2
  877. self.assertEqual(d1, Decimal('2'))
  878. #inline with other type
  879. d1 //= 2
  880. self.assertEqual(d1, Decimal('1'))
  881. def test_powering(self):
  882. d1 = Decimal('5')
  883. d2 = Decimal('2')
  884. #two Decimals
  885. self.assertEqual(d1**d2, Decimal('25'))
  886. self.assertEqual(d2**d1, Decimal('32'))
  887. #with other type, left
  888. c = d1 ** 4
  889. self.assertEqual(c, Decimal('625'))
  890. self.assertEqual(type(c), type(d1))
  891. #with other type, right
  892. c = 7 ** d1
  893. self.assertEqual(c, Decimal('16807'))
  894. self.assertEqual(type(c), type(d1))
  895. #inline with decimal
  896. d1 **= d2
  897. self.assertEqual(d1, Decimal('25'))
  898. #inline with other type
  899. d1 **= 4
  900. self.assertEqual(d1, Decimal('390625'))
  901. def test_module(self):
  902. d1 = Decimal('5')
  903. d2 = Decimal('2')
  904. #two Decimals
  905. self.assertEqual(d1%d2, Decimal('1'))
  906. self.assertEqual(d2%d1, Decimal('2'))
  907. #with other type, left
  908. c = d1 % 4
  909. self.assertEqual(c, Decimal('1'))
  910. self.assertEqual(type(c), type(d1))
  911. #with other type, right
  912. c = 7 % d1
  913. self.assertEqual(c, Decimal('2'))
  914. self.assertEqual(type(c), type(d1))
  915. #inline with decimal
  916. d1 %= d2
  917. self.assertEqual(d1, Decimal('1'))
  918. #inline with other type
  919. d1 %= 4
  920. self.assertEqual(d1, Decimal('1'))
  921. def test_floor_div_module(self):
  922. d1 = Decimal('5')
  923. d2 = Decimal('2')
  924. #two Decimals
  925. (p, q) = divmod(d1, d2)
  926. self.assertEqual(p, Decimal('2'))
  927. self.assertEqual(q, Decimal('1'))
  928. self.assertEqual(type(p), type(d1))
  929. self.assertEqual(type(q), type(d1))
  930. #with other type, left
  931. (p, q) = divmod(d1, 4)
  932. self.assertEqual(p, Decimal('1'))
  933. self.assertEqual(q, Decimal('1'))
  934. self.assertEqual(type(p), type(d1))
  935. self.assertEqual(type(q), type(d1))
  936. #with other type, right
  937. (p, q) = divmod(7, d1)
  938. self.assertEqual(p, Decimal('1'))
  939. self.assertEqual(q, Decimal('2'))
  940. self.assertEqual(type(p), type(d1))
  941. self.assertEqual(type(q), type(d1))
  942. def test_unary_operators(self):
  943. self.assertEqual(+Decimal(45), Decimal(+45)) # +
  944. self.assertEqual(-Decimal(45), Decimal(-45)) # -
  945. self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
  946. def test_nan_comparisons(self):
  947. # comparisons involving signaling nans signal InvalidOperation
  948. # order comparisons (<, <=, >, >=) involving only quiet nans
  949. # also signal InvalidOperation
  950. # equality comparisons (==, !=) involving only quiet nans
  951. # don't signal, but return False or True respectively.
  952. n = Decimal('NaN')
  953. s = Decimal('sNaN')
  954. i = Decimal('Inf')
  955. f = Decimal('2')
  956. qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
  957. snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
  958. order_ops = operator.lt, operator.le, operator.gt, operator.ge
  959. equality_ops = operator.eq, operator.ne
  960. # results when InvalidOperation is not trapped
  961. for x, y in qnan_pairs + snan_pairs:
  962. for op in order_ops + equality_ops:
  963. got = op(x, y)
  964. expected = True if op is operator.ne else False
  965. self.assertIs(expected, got,
  966. "expected {0!r} for operator.{1}({2!r}, {3!r}); "
  967. "got {4!r}".format(
  968. expected, op.__name__, x, y, got))
  969. # repeat the above, but this time trap the InvalidOperation
  970. with localcontext() as ctx:
  971. ctx.traps[InvalidOperation] = 1
  972. for x, y in qnan_pairs:
  973. for op in equality_ops:
  974. got = op(x, y)
  975. expected = True if op is operator.ne else False
  976. self.assertIs(expected, got,
  977. "expected {0!r} for "
  978. "operator.{1}({2!r}, {3!r}); "
  979. "got {4!r}".format(
  980. expected, op.__name__, x, y, got))
  981. for x, y in snan_pairs:
  982. for op in equality_ops:
  983. self.assertRaises(InvalidOperation, operator.eq, x, y)
  984. self.assertRaises(InvalidOperation, operator.ne, x, y)
  985. for x, y in qnan_pairs + snan_pairs:
  986. for op in order_ops:
  987. self.assertRaises(InvalidOperation, op, x, y)
  988. def test_copy_sign(self):
  989. d = Decimal(1).copy_sign(Decimal(-2))
  990. self.assertEqual(Decimal(1).copy_sign(-2), d)
  991. self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
  992. # The following are two functions used to test threading in the next class
  993. def thfunc1(cls):
  994. d1 = Decimal(1)
  995. d3 = Decimal(3)
  996. test1 = d1/d3
  997. cls.synchro.wait()
  998. test2 = d1/d3
  999. cls.finish1.set()
  1000. cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
  1001. cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
  1002. return
  1003. def thfunc2(cls):
  1004. d1 = Decimal(1)
  1005. d3 = Decimal(3)
  1006. test1 = d1/d3
  1007. thiscontext = getcontext()
  1008. thiscontext.prec = 18
  1009. test2 = d1/d3
  1010. cls.synchro.set()
  1011. cls.finish2.set()
  1012. cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
  1013. cls.assertEqual(test2, Decimal('0.333333333333333333'))
  1014. return
  1015. class DecimalUseOfContextTest(unittest.TestCase):
  1016. '''Unit tests for Use of Context cases in Decimal.'''
  1017. try:
  1018. import threading
  1019. except ImportError:
  1020. threading = None
  1021. # Take care executing this test from IDLE, there's an issue in threading
  1022. # that hangs IDLE and I couldn't find it
  1023. def test_threading(self):
  1024. #Test the "threading isolation" of a Context.
  1025. self.synchro = threading.Event()
  1026. self.finish1 = threading.Event()
  1027. self.finish2 = threading.Event()
  1028. th1 = threading.Thread(target=thfunc1, args=(self,))
  1029. th2 = threading.Thread(target=thfunc2, args=(self,))
  1030. th1.start()
  1031. th2.start()
  1032. self.finish1.wait()
  1033. self.finish2.wait()
  1034. return
  1035. if threading is None:
  1036. del test_threading
  1037. class DecimalUsabilityTest(unittest.TestCase):
  1038. '''Unit tests for Usability cases of Decimal.'''
  1039. def test_comparison_operators(self):
  1040. da = Decimal('23.42')
  1041. db = Decimal('23.42')
  1042. dc = Decimal('45')
  1043. #two Decimals
  1044. self.assertGreater(dc, da)
  1045. self.assertGreaterEqual(dc, da)
  1046. self.assertLess(da, dc)
  1047. self.assertLessEqual(da, dc)
  1048. self.assertEqual(da, db)
  1049. self.assertNotEqual(da, dc)
  1050. self.assertLessEqual(da, db)
  1051. self.assertGreaterEqual(da, db)
  1052. self.assertEqual(cmp(dc,da), 1)
  1053. self.assertEqual(cmp(da,dc), -1)
  1054. self.assertEqual(cmp(da,db), 0)
  1055. #a Decimal and an int
  1056. self.assertGreater(dc, 23)
  1057. self.assertLess(23, dc)
  1058. self.assertEqual(dc, 45)
  1059. self.assertEqual(cmp(dc,23), 1)
  1060. self.assertEqual(cmp(23,dc), -1)
  1061. self.assertEqual(cmp(dc,45), 0)
  1062. #a Decimal and uncomparable
  1063. self.assertNotEqual(da, 'ugly')
  1064. self.assertNotEqual(da, 32.7)
  1065. self.assertNotEqual(da, object())
  1066. self.assertNotEqual(da, object)
  1067. # sortable
  1068. a = map(Decimal, xrange(100))
  1069. b = a[:]
  1070. random.shuffle(a)
  1071. a.sort()
  1072. self.assertEqual(a, b)
  1073. # with None
  1074. with check_py3k_warnings():
  1075. self.assertFalse(Decimal(1) < None)
  1076. self.assertTrue(Decimal(1) > None)
  1077. def test_decimal_float_comparison(self):
  1078. da = Decimal('0.25')
  1079. db = Decimal('3.0')
  1080. self.assertLess(da, 3.0)
  1081. self.assertLessEqual(da, 3.0)
  1082. self.assertGreater(db, 0.25)
  1083. self.assertGreaterEqual(db, 0.25)
  1084. self.assertNotEqual(da, 1.5)
  1085. self.assertEqual(da, 0.25)
  1086. self.assertGreater(3.0, da)
  1087. self.assertGreaterEqual(3.0, da)
  1088. self.assertLess(0.25, db)
  1089. self.assertLessEqual(0.25, db)
  1090. self.assertNotEqual(0.25, db)
  1091. self.assertEqual(3.0, db)
  1092. self.assertNotEqual(0.1, Decimal('0.1'))
  1093. def test_copy_and_deepcopy_methods(self):
  1094. d = Decimal('43.24')
  1095. c = copy.copy(d)
  1096. self.assertEqual(id(c), id(d))
  1097. dc = copy.deepcopy(d)
  1098. self.assertEqual(id(dc), id(d))
  1099. def test_hash_method(self):
  1100. #just that it's hashable
  1101. hash(Decimal(23))
  1102. hash(Decimal('Infinity'))
  1103. hash(Decimal('-Infinity'))
  1104. hash(Decimal('nan123'))
  1105. hash(Decimal('-NaN'))
  1106. test_values = [Decimal(sign*(2**m + n))
  1107. for m in [0, 14, 15, 16, 17, 30, 31,
  1108. 32, 33, 62, 63, 64, 65, 66]
  1109. for n in range(-10, 10)
  1110. for sign in [-1, 1]]
  1111. test_values.extend([
  1112. Decimal("-0"), # zeros
  1113. Decimal("0.00"),
  1114. Decimal("-0.000"),
  1115. Decimal("0E10"),
  1116. Decimal("-0E12"),
  1117. Decimal("10.0"), # negative exponent
  1118. Decimal("-23.00000"),
  1119. Decimal("1230E100"), # positive exponent
  1120. Decimal("-4.5678E50"),
  1121. # a value for which hash(n) != hash(n % (2**64-1))
  1122. # in Python pre-2.6
  1123. Decimal(2**64 + 2**32 - 1),
  1124. # selection of values which fail with the old (before
  1125. # version 2.6) long.__hash__
  1126. Decimal("1.634E100"),
  1127. Decimal("90.697E100"),
  1128. Decimal("188.83E100"),
  1129. Decimal("1652.9E100"),
  1130. Decimal("56531E100"),
  1131. ])
  1132. # check that hash(d) == hash(int(d)) for integral values
  1133. for value in test_values:
  1134. self.assertEqual(hash(value), hash(int(value)))
  1135. #the same hash that to an int
  1136. self.assertEqual(hash(Decimal(23)), hash(23))
  1137. self.assertRaises(TypeError, hash, Decimal('sNaN'))
  1138. self.assertTrue(hash(Decimal('Inf')))
  1139. self.assertTrue(hash(Decimal('-Inf')))
  1140. # check that the hashes of a Decimal float match when they
  1141. # represent exactly the same values
  1142. test_strings = ['inf', '-Inf', '0.0', '-.0e1',
  1143. '34.0', '2.5', '112390.625', '-0.515625']
  1144. for s in test_strings:
  1145. f = float(s)
  1146. d = Decimal(s)
  1147. self.assertEqual(hash(f), hash(d))
  1148. # check that the value of the hash doesn't depend on the
  1149. # current context (issue #1757)
  1150. c = getcontext()
  1151. old_precision = c.prec
  1152. x = Decimal("123456789.1")
  1153. c.prec = 6
  1154. h1 = hash(x)
  1155. c.prec = 10
  1156. h2 = hash(x)
  1157. c.prec = 16
  1158. h3 = hash(x)
  1159. self.assertEqual(h1, h2)
  1160. self.assertEqual(h1, h3)
  1161. c.prec = old_precision
  1162. def test_min_and_max_methods(self):
  1163. d1 = Decimal('15.32')
  1164. d2 = Decimal('28.5')
  1165. l1 = 15
  1166. l2 = 28
  1167. #between Decimals
  1168. self.assertIs(min(d1,d2), d1)
  1169. self.assertIs(min(d2,d1), d1)
  1170. self.assertIs(max(d1,d2), d2)
  1171. self.assertIs(max(d2,d1), d2)
  1172. #between Decimal and long
  1173. self.assertIs(min(d1,l2), d1)
  1174. self.assertIs(min(l2,d1), d1)
  1175. self.assertIs(max(l1,d2), d2)
  1176. self.assertIs(max(d2,l1), d2)
  1177. def test_as_nonzero(self):
  1178. #as false
  1179. self.assertFalse(Decimal(0))
  1180. #as true
  1181. self.assertTrue(Decimal('0.372'))
  1182. def test_tostring_methods(self):
  1183. #Test str and repr methods.
  1184. d = Decimal('15.32')
  1185. self.assertEqual(str(d), '15.32') # str
  1186. self.assertEqual(repr(d), "Decimal('15.32')") # repr
  1187. # result type of string methods should be str, not unicode
  1188. unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
  1189. u'-0.0E100', u'-NaN001', u'-Inf']
  1190. for u in unicode_inputs:
  1191. d = Decimal(u)
  1192. self.assertEqual(type(str(d)), str)
  1193. self.assertEqual(type(repr(d)), str)
  1194. self.assertEqual(type(d.to_eng_string()), str)
  1195. def test_tonum_methods(self):
  1196. #Test float, int and long methods.
  1197. d1 = Decimal('66')
  1198. d2 = Decimal('15.32')
  1199. #int
  1200. self.assertEqual(int(d1), 66)
  1201. self.assertEqual(int(d2), 15)
  1202. #long
  1203. self.assertEqual(long(d1), 66)
  1204. self.assertEqual(long(d2), 15)
  1205. #float
  1206. self.assertEqual(float(d1), 66)
  1207. self.assertEqual(float(d2), 15.32)
  1208. def test_eval_round_trip(self):
  1209. #with zero
  1210. d = Decimal( (0, (0,), 0) )
  1211. self.assertEqual(d, eval(repr(d)))
  1212. #int
  1213. d = Decimal( (1, (4, 5), 0) )
  1214. self.assertEqual(d, eval(repr(d)))
  1215. #float
  1216. d = Decimal( (0, (4, 5, 3, 4), -2) )
  1217. self.assertEqual(d, eval(repr(d)))
  1218. #weird
  1219. d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
  1220. self.assertEqual(d, eval(repr(d)))
  1221. def test_as_tuple(self):
  1222. #with zero
  1223. d = Decimal(0)
  1224. self.assertEqual(d.as_tuple(), (0, (0,), 0) )
  1225. #int
  1226. d = Decimal(-45)
  1227. self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
  1228. #complicated string
  1229. d = Decimal("-4.34913534E-17")
  1230. self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
  1231. #inf
  1232. d = Decimal("Infinity")
  1233. self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
  1234. #leading zeros in coefficient should be stripped
  1235. d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
  1236. self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
  1237. d = Decimal( (1, (0, 0, 0), 37) )
  1238. self.assertEqual(d.as_tuple(), (1, (0,), 37))
  1239. d = Decimal( (1, (), 37) )
  1240. se

Large files files are truncated, but you can click here to view the full file