[Python-checkins] python/nondist/sandbox/decimal Decimal.py, 1.24,
1.25 test_Decimal.py, 1.19, 1.20
rhettinger at users.sourceforge.net
rhettinger at users.sourceforge.net
Tue Jun 29 06:08:39 EDT 2004
Update of /cvsroot/python/python/nondist/sandbox/decimal
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10586
Modified Files:
Decimal.py test_Decimal.py
Log Message:
Prepare Decimal to move into the core.
* With agreement from the principal contributors, removed the BSD
license and added a PSF copyright.
* Remove version history. CVS will track that now.
* Add a todo list.
* Made Decimal() == Decimal("0").
* Added pickle support for Decimal objects.
* Copy and deepcopy now return self (as all good immutables do).
* Run doctest on the docstrings.
* Group the test suites together so their results can be aggregated.
* Replaced variable names that shadowed imports or builtins (this
excludes "divmod" which seemed to be the variable name).
Index: Decimal.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/decimal/Decimal.py,v
retrieving revision 1.24
retrieving revision 1.25
diff -C2 -d -r1.24 -r1.25
*** Decimal.py 25 Jun 2004 17:46:20 -0000 1.24
--- Decimal.py 29 Jun 2004 10:08:35 -0000 1.25
***************
*** 1,7 ****
! # Class Decimal, version 0.7.1
! # Written by Eric Price <eprice at tjhsst.edu>
! # and Facundo Batista <facundo at taniquetil.com.ar>
! # Based on code written by Aahz (aahz at pobox.com)
! # Currently under BSD-style license (copyright 2003)
"""
This is a stab at a decimal arithmetic module based on the decimal
--- 1,19 ----
! # Copyright (c) 2004 Python Software Foundation.
! # All rights reserved.
!
! # Written by Eric Price <eprice at tjhsst.edu>
! # and Facundo Batista <facundo at taniquetil.com.ar>
! # and Raymond Hettinger <python at rcn.com>
! # and Aahz (aahz at pobox.com)
! # and Tim Peters
!
!
! # Todo:
! # Add deepcopy and pickle support for contexts
! # Rename to decimal.Decimal before moving into production
! # Consider having a SimpleDecimal subclass implementing X3.274 semantics
! # Add an __all__ attribute
! # Improve docstrings and add more doctests
!
"""
This is a stab at a decimal arithmetic module based on the decimal
***************
*** 95,132 ****
"""
! # facundobatista:
! # 0.8.2 2004.06.24 Lot of small clean-ups from Raymond Hettinger.
! # 0.8.1 2004.06.23 Complies with immutability-near as discussed in c.l.py.
! # 0.8.0 2004.06.21 Using the updated Spec (and complies with new test cases) from
! # Cowlishaw. Deprecated trim and rescale. Changed __str__ and
! # __repr__ to return in sci format, added as_tuple(). Fixed the
! # initial examples. Extracted lt, gt and eq methods from context.
! # Added copy method to context.
! # 0.7.6 2004.06.20 More name changes. Extracted InsufficientStorage exception.
! # Added create_decimal to context.
! # 0.7.5 2004.06.19 Lots of name changes.
! # 0.7.4 2004.04.05 Added rdiv, rdivmod, rmod, rpow, rfloordiv special methods.
! # Fixed sub.
! # 0.7.3 2004.04.04 Added _convert_other method, for implicit constructions,
! # and more checks when constructing from tuples. Fixed
! # __sub__ to modify a copy of the instance.
! # 0.7.2 2004.04.02 Fixed __pow__ to run the example ok. Added from_float
! # method. Fixed isnan to accept empty strings.
! # 0.7.1 2004.03.08 Corrected initial examples
!
! # eprice:
! # 0.7.0 2003.2.28 More changes. Contexts done nicely, exponent limits
! # 0.6.0 2003.2.24 Many changes. No exponent limits
!
! # Aahz:
! # 0.0.8 2001.5.24 Fixed multiplication with trailing zeroes
! # 0.0.7 2001.5.23 Fixed string conversion to follow spec
! # 0.0.6 2001.5.20 Tim Peters's _floatToString()
! # 0.0.5 2001.5.20 Now with multiplication, round(), and conversions
! # 0.0.0 2001.5.18 First public release with just addition/subtraction
!
! # To-do list:
! #
! # Cleanup, hunt and kill bugs
import threading
--- 107,111 ----
"""
! # XXX Add an __all__ attribute
import threading
***************
*** 137,141 ****
#Capitals: 1E+10, not 1e10
-
CAPITALS = 1
--- 116,119 ----
***************
*** 401,404 ****
--- 379,383 ----
return context
+
class Decimal(object):
"""Floating point class for decimal arithmetic."""
***************
*** 406,410 ****
__slots__ = ('_exp','_int','_sign')
! def __init__(self, value, context = None):
"""Initialize the Decimal class.
--- 385,389 ----
__slots__ = ('_exp','_int','_sign')
! def __init__(self, value="0", context=None):
"""Initialize the Decimal class.
***************
*** 420,423 ****
--- 399,403 ----
if context is None:
context = getcontext()
+
# String?
# REs insist on real strings, so we can too.
***************
*** 448,451 ****
--- 428,432 ----
return
+ ### XXX Hmm, with precision=3, Decimal(12345) fails with Decimal('12345') works
if isinstance(value, (int,long)):
# checking that the int or long doesn't exceed precision
***************
*** 1795,1810 ****
return ans
! copy = self._fix(context=context)
! if copy._isinfinity():
! return copy
! if not copy:
! return Decimal( (copy._sign, (0,), 0) )
! end = len(copy._int)
! exp = copy._exp
! while copy._int[end-1] == 0:
exp += 1
end -= 1
! return Decimal( (copy._sign, copy._int[:end], exp) )
--- 1776,1791 ----
return ans
! dup = self._fix(context=context)
! if dup._isinfinity():
! return dup
! if not dup:
! return Decimal( (dup._sign, (0,), 0) )
! end = len(dup._int)
! exp = dup._exp
! while dup._int[end-1] == 0:
exp += 1
end -= 1
! return Decimal( (dup._sign, dup._int[:end], exp) )
***************
*** 2110,2113 ****
--- 2091,2104 ----
exp = property(_get_exp)
+ # support for pickling, copy, and deepcopy
+ def __reduce__(self):
+ return (self.__class__, (str(self),))
+
+ def __copy__(self):
+ return self # I'm immutable; therefore I am my own clone
+
+ def __deepcopy__(self, memo):
+ return self # My components are also immutable
+
# get rounding method function:
***************
*** 2202,2205 ****
--- 2193,2197 ----
"""Returns Etiny (= Emin - prec + 1)"""
return long(self.Emin - self.prec + 1)
+
def Etop(self):
"""Returns maximum exponent (= Emin - prec + 1)"""
***************
*** 2375,2379 ****
curspot -= 1
! def subtract(self, list):
"""Subtract a list from the current int (in place).
--- 2367,2371 ----
curspot -= 1
! def subtract(self, alist):
"""Subtract a list from the current int (in place).
***************
*** 2384,2392 ****
self.int.reverse()
! list.reverse()
carry = 0
! for x in xrange(len(list)):
! self.int[x] -= list[x] + carry
if self.int[x] < 0:
carry = 1
--- 2376,2384 ----
self.int.reverse()
! alist.reverse()
carry = 0
! for x in xrange(len(alist)):
! self.int[x] -= alist[x] + carry
if self.int[x] < 0:
carry = 1
***************
*** 2403,2407 ****
self.int[last+1:]=[]
self.int.reverse()
! list.reverse()
return
--- 2395,2399 ----
self.int[last+1:]=[]
self.int.reverse()
! alist.reverse()
return
***************
*** 2753,2755 ****
return "%s%se%d" % (sign, str(top), e)
-
--- 2745,2746 ----
Index: test_Decimal.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/decimal/test_Decimal.py,v
retrieving revision 1.19
retrieving revision 1.20
diff -C2 -d -r1.19 -r1.20
*** test_Decimal.py 25 Jun 2004 01:30:49 -0000 1.19
--- test_Decimal.py 29 Jun 2004 10:08:35 -0000 1.20
***************
*** 1,5 ****
! # Test Cases for Decimal module, version 0.1.1
! # Written by Eric Price <eprice at tjhsst.edu>
! # and Facundo Batista <facundo at taniquetil.com.ar>
"""
These are the test cases for the Decimal module.
--- 1,11 ----
! # Copyright (c) 2004 Python Software Foundation.
! # All rights reserved.
!
! # Written by Eric Price <eprice at tjhsst.edu>
! # and Facundo Batista <facundo at taniquetil.com.ar>
! # and Raymond Hettinger <python at rcn.com>
! # and Aahz (aahz at pobox.com)
! # and Tim Peters
!
"""
These are the test cases for the Decimal module.
***************
*** 15,43 ****
"""
- # 0.2.1 2004.06.23 fb: Added immutability test for operations.
- # 0.2.0 2004.06.21 fb: Using the new test cases from Cowlishaw. Deprecated trim
- # test case and use of result in inexact test case. Added
- # as_tuple() test case.
- # 0.1.9 2004.06.20 fb: More fixes because of the name changes. Added test case for
- # context.create_decimal().
- # 0.1.8 2004.06.19 fb: Adjusted threading test case. Taken out the immutability
- # test. Added tearDown method to DecimalTest class. Some fixes
- # because of the name changes.
- # 0.1.7 2004.04.05 fb: Adjusted several test cases. Eliminated interaction
- # with float in comparations and min/max test cases.
- # 0.1.6 2004.04.04 fb: Extended explicit construction test case from tuples.
- # 0.1.5 2004.04.02 fb: Adjusted explicit construction test cases.
- # 0.1.4 2004.03.28 fb: Added Use of Context and Decimal Usability test cases.
- # Corrected tests using try/except/else.
- # 0.1.3 2004.03.23 fb: Added arithmetic operators test and corrected minor
- # method case issues.
- # 0.1.2 2004.03.20 fb: Added from_float to explicit construction test cases
- # and all implicit construction test cases. Also upgraded
- # method names to new GvR definiton.
- # 0.1.1 2004.03.11 fb: Added Explicit Construction tests
- # 0.1.0 2004.03.11 fb: Placed the structure to run separate test groups
- #
- # fb = facundobatista
-
from __future__ import division
--- 21,24 ----
***************
*** 45,51 ****
import glob
import os, sys
from Decimal import *
! from test.test_support import TestSkipped, run_unittest
--- 26,33 ----
import glob
import os, sys
+ import pickle, copy
from Decimal import *
! from test.test_support import TestSkipped, run_unittest, run_doctest
***************
*** 90,94 ****
# Name adapter to be able to change the Decimal and Context
! # interface without changing the test files from Cowlishaw
nameAdapter = {'toeng':'to_eng_string',
'tosci':'to_sci_string',
--- 72,76 ----
# Name adapter to be able to change the Decimal and Context
! # interface without changing the test files from Cowlishaw
nameAdapter = {'toeng':'to_eng_string',
'tosci':'to_sci_string',
***************
*** 144,148 ****
#Exception raised where there shoudn't have been one.
self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
!
return
--- 126,130 ----
#Exception raised where there shoudn't have been one.
self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
!
return
***************
*** 200,204 ****
fname = nameAdapter.get(funct, funct)
if fname == 'rescale':
! return
funct = getattr(self.context, fname)
vals = []
--- 182,186 ----
fname = nameAdapter.get(funct, funct)
if fname == 'rescale':
! return
funct = getattr(self.context, fname)
vals = []
***************
*** 234,238 ****
else:
self.fail("Did not raise %s in %s" % (error, s))
! self.context.trap_enablers[error] = 0
v = self.context.create_decimal(v)
else:
--- 216,220 ----
else:
self.fail("Did not raise %s in %s" % (error, s))
! self.context.trap_enablers[error] = 0
v = self.context.create_decimal(v)
else:
***************
*** 241,245 ****
ans = FixQuotes(ans)
!
if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
for error in theirexceptions:
--- 223,227 ----
ans = FixQuotes(ans)
!
if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
for error in theirexceptions:
***************
*** 254,258 ****
else:
self.fail("Did not raise %s in %s" % (error, s))
! self.context.trap_enablers[error] = 0
try:
result = str(funct(*vals))
--- 236,240 ----
else:
self.fail("Did not raise %s in %s" % (error, s))
! self.context.trap_enablers[error] = 0
try:
result = str(funct(*vals))
***************
*** 490,494 ****
def test_empty(self):
'''Explicit construction without parameters.'''
! self.assertRaises(TypeError, Decimal)
def test_from_None(self):
--- 472,476 ----
def test_empty(self):
'''Explicit construction without parameters.'''
! self.assertEqual(Decimal(), Decimal("0"))
def test_from_None(self):
***************
*** 510,514 ****
d = Decimal(-45)
self.assertEqual(str(d), '-45')
!
#zero
d = Decimal(0)
--- 492,496 ----
d = Decimal(-45)
self.assertEqual(str(d), '-45')
!
#zero
d = Decimal(0)
***************
*** 525,529 ****
d = Decimal('45')
self.assertEqual(str(d), '45')
!
#float
d = Decimal('45.34')
--- 507,511 ----
d = Decimal('45')
self.assertEqual(str(d), '45')
!
#float
d = Decimal('45.34')
***************
*** 548,552 ****
d = Decimal.from_float(-32.0)
self.assertEqual(str(d), '-32')
!
#zero
d = Decimal.from_float(0.0)
--- 530,534 ----
d = Decimal.from_float(-32.0)
self.assertEqual(str(d), '-32')
!
#zero
d = Decimal.from_float(0.0)
***************
*** 565,573 ****
d = Decimal.from_float(2.2)
self.assertEqual(str(d), '2.20000000000000017763568394002504646778106689453125')
!
#inexact float, rounded to some positions
d = Decimal.from_float(2.2, 16)
self.assertEqual(str(d), '2.2000000000000002')
!
#inexact float, rounded to less positions
d = Decimal.from_float(2.2, 5)
--- 547,555 ----
d = Decimal.from_float(2.2)
self.assertEqual(str(d), '2.20000000000000017763568394002504646778106689453125')
!
#inexact float, rounded to some positions
d = Decimal.from_float(2.2, 16)
self.assertEqual(str(d), '2.2000000000000002')
!
#inexact float, rounded to less positions
d = Decimal.from_float(2.2, 5)
***************
*** 584,588 ****
d = Decimal( (1, (4, 5), 0) )
self.assertEqual(str(d), '-45')
!
#float
d = Decimal( (0, (4, 5, 3, 4), -2) )
--- 566,570 ----
d = Decimal( (1, (4, 5), 0) )
self.assertEqual(str(d), '-45')
!
#float
d = Decimal( (0, (4, 5, 3, 4), -2) )
***************
*** 626,630 ****
self.assertEqual(str(e), '-45')
self.assertNotEqual(id(d), id(e))
!
#zero
d = Decimal(0)
--- 608,612 ----
self.assertEqual(str(e), '-45')
self.assertNotEqual(id(d), id(e))
!
#zero
d = Decimal(0)
***************
*** 688,692 ****
else:
self.fail('Did not raised an error!')
!
def test_from_int(self):
'''Implicit construction with int or long.'''
--- 670,674 ----
else:
self.fail('Did not raised an error!')
!
def test_from_int(self):
'''Implicit construction with int or long.'''
***************
*** 704,708 ****
else:
self.fail('Did not raised an error!')
!
def test_from_string(self):
'''Implicit construction with string.'''
--- 686,690 ----
else:
self.fail('Did not raised an error!')
!
def test_from_string(self):
'''Implicit construction with string.'''
***************
*** 1010,1014 ****
def test_threading(self):
'''Test the "threading isolation" of a Context.'''
!
self.synchro = threading.Event()
self.finish1 = threading.Event()
--- 992,996 ----
def test_threading(self):
'''Test the "threading isolation" of a Context.'''
!
self.synchro = threading.Event()
self.finish1 = threading.Event()
***************
*** 1073,1088 ****
'''Test copy and deepcopy.'''
- import copy
d = Decimal('43.24')
-
- #copy
c = copy.copy(d)
! self.assertEqual(c, d)
! self.assertNotEqual(id(c), id(d))
!
! #deepcopy
dc = copy.deepcopy(d)
! self.assertEqual(dc, d)
! self.assertNotEqual(id(dc), id(d))
def test_hash_method(self):
--- 1055,1063 ----
'''Test copy and deepcopy.'''
d = Decimal('43.24')
c = copy.copy(d)
! self.assertEqual(id(c), id(d))
dc = copy.deepcopy(d)
! self.assertEqual(id(dc), id(d))
def test_hash_method(self):
***************
*** 1123,1127 ****
#as true
self.failUnless(Decimal('0.372'))
!
def test_tostring_methods(self):
'''Test str and repr methods.'''
--- 1098,1102 ----
#as true
self.failUnless(Decimal('0.372'))
!
def test_tostring_methods(self):
'''Test str and repr methods.'''
***************
*** 1134,1138 ****
#repr
self.assertEqual(repr(d), 'Decimal("15.32")')
!
def test_tonum_methods(self):
'''Test float, int and long methods.'''
--- 1109,1113 ----
#repr
self.assertEqual(repr(d), 'Decimal("15.32")')
!
def test_tonum_methods(self):
'''Test float, int and long methods.'''
***************
*** 1163,1167 ****
d = Decimal( (1, (4, 5), 0) )
self.assertEqual(d, eval(repr(d)))
!
#float
d = Decimal( (0, (4, 5, 3, 4), -2) )
--- 1138,1142 ----
d = Decimal( (1, (4, 5), 0) )
self.assertEqual(d, eval(repr(d)))
!
#float
d = Decimal( (0, (4, 5, 3, 4), -2) )
***************
*** 1182,1186 ****
d = Decimal(-45)
self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
!
#complicated string
d = Decimal("-4.34913534E-17")
--- 1157,1161 ----
d = Decimal(-45)
self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
!
#complicated string
d = Decimal("-4.34913534E-17")
***************
*** 1247,1251 ****
self.assertEqual(d1._int, b1._int)
self.assertEqual(d1._exp, b1._exp)
!
checkSameDec("__abs__")
checkSameDec("__add__", True)
--- 1222,1226 ----
self.assertEqual(d1._int, b1._int)
self.assertEqual(d1._exp, b1._exp)
!
checkSameDec("__abs__")
checkSameDec("__add__", True)
***************
*** 1289,1295 ****
checkSameDec("to_integral")
! def test_main(which=None):
""" Execute the tests.
--- 1264,1276 ----
checkSameDec("to_integral")
+ class DecimalPythonAPItests(unittest.TestCase):
+ def test_pickle(self):
+ d = Decimal('-3.141590000')
+ p = pickle.dumps(d)
+ e = pickle.loads(p)
+ self.assertEqual(d, e)
! def test_main(which=None, verbose=None):
""" Execute the tests.
***************
*** 1298,1312 ****
Otherwise, executes both of them.
"""
if which == "Arithmetic" or which is None:
! run_unittest(DecimalTest)
if which == "Behaviour" or which is None:
! run_unittest(DecimalExplicitConstructionTest)
! run_unittest(DecimalImplicitConstructionTest)
! run_unittest(DecimalArithmeticOperatorsTest)
! run_unittest(DecimalUseOfContextTest)
! run_unittest(DecimalUsabilityTest)
!
return
--- 1279,1300 ----
Otherwise, executes both of them.
"""
+ test_classes = []
if which == "Arithmetic" or which is None:
! test_classes.extend([DecimalTest])
if which == "Behaviour" or which is None:
! test_classes.extend([
! DecimalExplicitConstructionTest,
! DecimalImplicitConstructionTest,
! DecimalArithmeticOperatorsTest,
! DecimalUseOfContextTest,
! DecimalUsabilityTest,
! DecimalPythonAPItests,
! ])
!
! run_unittest(*test_classes)
! import Decimal as DecimalModule
! run_doctest(DecimalModule, verbose)
return
***************
*** 1314,1320 ****
if __name__ == '__main__':
if len(sys.argv) == 1:
! test_main()
elif len(sys.argv) == 2:
! test_main(sys.argv[1])
else:
raise ValueError, "test called with wrong arguments, use test_Decimal [Arithmetic|Behaviour]"
--- 1302,1308 ----
if __name__ == '__main__':
if len(sys.argv) == 1:
! test_main(verbose=True)
elif len(sys.argv) == 2:
! test_main(sys.argv[1], verbose=True)
else:
raise ValueError, "test called with wrong arguments, use test_Decimal [Arithmetic|Behaviour]"
More information about the Python-checkins
mailing list