Add normalize option to Decimal type
This commit is contained in:
@@ -23,6 +23,9 @@ Features
|
|||||||
|
|
||||||
- Add `NoneOf` validator wich succeeds if the value is none of the choices.
|
- Add `NoneOf` validator wich succeeds if the value is none of the choices.
|
||||||
|
|
||||||
|
- Add ``normalize`` option to ``Decimal``, stripping the rightmost
|
||||||
|
trailing zeros.
|
||||||
|
|
||||||
Bug Fixes
|
Bug Fixes
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
@@ -1305,24 +1305,27 @@ class Decimal(Number):
|
|||||||
method of this class, the :attr:`colander.null` value will be
|
method of this class, the :attr:`colander.null` value will be
|
||||||
returned.
|
returned.
|
||||||
|
|
||||||
The Decimal constructor takes two optional arguments, ``quant`` and
|
The Decimal constructor takes three optional arguments, ``quant``,
|
||||||
``rounding``. If supplied, ``quant`` should be a string,
|
``rounding`` and ``normalize``. If supplied, ``quant`` should be a string,
|
||||||
(e.g. ``1.00``). If supplied, ``rounding`` should be one of the Python
|
(e.g. ``1.00``). If supplied, ``rounding`` should be one of the Python
|
||||||
``decimal`` module rounding options (e.g. ``decimal.ROUND_UP``,
|
``decimal`` module rounding options (e.g. ``decimal.ROUND_UP``,
|
||||||
``decimal.ROUND_DOWN``, etc). The serialized and deserialized result
|
``decimal.ROUND_DOWN``, etc). The serialized and deserialized result
|
||||||
will be quantized and rounded via
|
will be quantized and rounded via
|
||||||
``result.quantize(decimal.Decimal(quant), rounding)``. ``rounding`` is
|
``result.quantize(decimal.Decimal(quant), rounding)``. ``rounding`` is
|
||||||
ignored if ``quant`` is not supplied.
|
ignored if ``quant`` is not supplied. If ``normalize`` is ``True``,
|
||||||
|
the serialized and deserialized result will be normalized by stripping
|
||||||
|
the rightmost trailing zeros.
|
||||||
|
|
||||||
The subnodes of the :class:`colander.SchemaNode` that wraps
|
The subnodes of the :class:`colander.SchemaNode` that wraps
|
||||||
this type are ignored.
|
this type are ignored.
|
||||||
"""
|
"""
|
||||||
def __init__(self, quant=None, rounding=None):
|
def __init__(self, quant=None, rounding=None, normalize=False):
|
||||||
if quant is None:
|
if quant is None:
|
||||||
self.quant = None
|
self.quant = None
|
||||||
else:
|
else:
|
||||||
self.quant = decimal.Decimal(quant)
|
self.quant = decimal.Decimal(quant)
|
||||||
self.rounding = rounding
|
self.rounding = rounding
|
||||||
|
self.normalize = normalize
|
||||||
|
|
||||||
def num(self, val):
|
def num(self, val):
|
||||||
result = decimal.Decimal(str(val))
|
result = decimal.Decimal(str(val))
|
||||||
@@ -1331,6 +1334,8 @@ class Decimal(Number):
|
|||||||
result = result.quantize(self.quant)
|
result = result.quantize(self.quant)
|
||||||
else:
|
else:
|
||||||
result = result.quantize(self.quant, self.rounding)
|
result = result.quantize(self.quant, self.rounding)
|
||||||
|
if self.normalize:
|
||||||
|
result = result.normalize()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
class Money(Decimal):
|
class Money(Decimal):
|
||||||
@@ -1346,8 +1351,7 @@ class Money(Decimal):
|
|||||||
this type are ignored.
|
this type are ignored.
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.quant = decimal.Decimal('.01')
|
super(Money, self).__init__(decimal.Decimal('.01'), decimal.ROUND_UP)
|
||||||
self.rounding = decimal.ROUND_UP
|
|
||||||
|
|
||||||
class Boolean(SchemaType):
|
class Boolean(SchemaType):
|
||||||
""" A type representing a boolean object.
|
""" A type representing a boolean object.
|
||||||
|
@@ -1691,9 +1691,9 @@ class TestFloat(unittest.TestCase):
|
|||||||
self.assertEqual(result, '1.0')
|
self.assertEqual(result, '1.0')
|
||||||
|
|
||||||
class TestDecimal(unittest.TestCase):
|
class TestDecimal(unittest.TestCase):
|
||||||
def _makeOne(self, quant=None, rounding=None):
|
def _makeOne(self, quant=None, rounding=None, normalize=False):
|
||||||
from colander import Decimal
|
from colander import Decimal
|
||||||
return Decimal(quant, rounding)
|
return Decimal(quant, rounding, normalize)
|
||||||
|
|
||||||
def test_serialize_null(self):
|
def test_serialize_null(self):
|
||||||
import colander
|
import colander
|
||||||
@@ -1725,6 +1725,14 @@ class TestDecimal(unittest.TestCase):
|
|||||||
result = typ.serialize(node, val)
|
result = typ.serialize(node, val)
|
||||||
self.assertEqual(result, '0.01')
|
self.assertEqual(result, '0.01')
|
||||||
|
|
||||||
|
def test_serialize_normalize(self):
|
||||||
|
from decimal import Decimal
|
||||||
|
val = Decimal('1.00')
|
||||||
|
node = DummySchemaNode(None)
|
||||||
|
typ = self._makeOne(normalize=True)
|
||||||
|
result = typ.serialize(node, val)
|
||||||
|
self.assertEqual(result, '1')
|
||||||
|
|
||||||
def test_deserialize_fails(self):
|
def test_deserialize_fails(self):
|
||||||
val = 'P'
|
val = 'P'
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
@@ -1748,6 +1756,15 @@ class TestDecimal(unittest.TestCase):
|
|||||||
result = typ.deserialize(node, val)
|
result = typ.deserialize(node, val)
|
||||||
self.assertEqual(result, decimal.Decimal('1.01'))
|
self.assertEqual(result, decimal.Decimal('1.01'))
|
||||||
|
|
||||||
|
def test_deserialize_with_normalize(self):
|
||||||
|
from decimal import Decimal
|
||||||
|
val = '1.00'
|
||||||
|
node = DummySchemaNode(None)
|
||||||
|
typ = self._makeOne(normalize=True)
|
||||||
|
result = typ.deserialize(node, val)
|
||||||
|
self.assertEqual(result, Decimal('1'))
|
||||||
|
self.assertEqual(str(result), '1')
|
||||||
|
|
||||||
def test_serialize_fails(self):
|
def test_serialize_fails(self):
|
||||||
val = 'P'
|
val = 'P'
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
|
Reference in New Issue
Block a user