Fix FloatEquivalenceTester. If decimal_alignment was enabled, the tester could...

Fix FloatEquivalenceTester. If decimal_alignment was enabled, the tester could compare floats to Decimals, which in Python 2.6 silently returns incorrect results (Decimals and floats always sort the same, no matter their magnitude)

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@44574 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent f574132b
...@@ -28,11 +28,18 @@ ...@@ -28,11 +28,18 @@
# #
############################################################################## ##############################################################################
import decimal
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type.Core.Predicate import Predicate from Products.ERP5Type.Core.Predicate import Predicate
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.mixin.equivalence_tester import EquivalenceTesterMixin from Products.ERP5.mixin.equivalence_tester import EquivalenceTesterMixin
# On Python 2.4, this dictionary doesn't include ROUND_05UP
ROUNDING_OPTION_DICT = dict((name, value)
for name, value in decimal.__dict__.items()
if name.startswith('ROUND_'))
# On Python >= 2.6, we could compute a value based on sys.float_info.epsilon # On Python >= 2.6, we could compute a value based on sys.float_info.epsilon
DEFAULT_PRECISION = 1e-12 DEFAULT_PRECISION = 1e-12
...@@ -164,18 +171,18 @@ class FloatEquivalenceTester(Predicate, EquivalenceTesterMixin): ...@@ -164,18 +171,18 @@ class FloatEquivalenceTester(Predicate, EquivalenceTesterMixin):
value=relative_tolerance_max)) value=relative_tolerance_max))
def _round(self, value): def _round(self, value):
from decimal import (Decimal, ROUND_DOWN, ROUND_UP, ROUND_CEILING, # on Python 2.4, looking up 'ROUND_05UP' will return ROUND_DOWN here
ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, rounding_option = ROUNDING_OPTION_DICT.get(self.getDecimalRoundingOption(),
ROUND_HALF_UP) decimal.ROUND_DOWN)
# Python2.4 did not support ROUND_05UP yet. exponent = decimal.Decimal(self.getDecimalExponent())
rounding_option_dict = {'ROUND_DOWN':ROUND_DOWN, # In Python 2.7, the str() below will no longer be necessary
'ROUND_UP':ROUND_UP, result = decimal.Decimal(str(value)).quantize(exponent,
'ROUND_CEILING':ROUND_CEILING, rounding=rounding_option)
'ROUND_FLOOR':ROUND_FLOOR, # XXX everything in ERP5 is in float and, in Python 2.6, Decimals
'ROUND_HALF_DOWN':ROUND_HALF_DOWN, # and floats don't compare numerically, ex:
'ROUND_HALF_EVEN':ROUND_HALF_EVEN, # Decimal(1) < 2. is False
'ROUND_HALF_UP':ROUND_HALF_UP} #
rounding_option = rounding_option_dict.get(self.getDecimalRoundingOption(), # So we downcast the return value to float here. If ERP5 is
ROUND_DOWN) # converted to Decimals everywhere, then the float() call should
return Decimal(str(value)).quantize(Decimal(self.getDecimalExponent()), # go away
rounding=rounding_option) return float(result)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment