Merge pull request #3248 from durocher/master

Fix approx default tolerances for Decimal
This commit is contained in:
Ronny Pfannschmidt 2018-02-22 07:35:56 +01:00 committed by GitHub
commit 264e455410
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 2 deletions

View File

@ -153,6 +153,8 @@ class ApproxScalar(ApproxBase):
""" """
Perform approximate comparisons for single numbers only. Perform approximate comparisons for single numbers only.
""" """
DEFAULT_ABSOLUTE_TOLERANCE = 1e-12
DEFAULT_RELATIVE_TOLERANCE = 1e-6
def __repr__(self): def __repr__(self):
""" """
@ -223,7 +225,7 @@ class ApproxScalar(ApproxBase):
# Figure out what the absolute tolerance should be. ``self.abs`` is # Figure out what the absolute tolerance should be. ``self.abs`` is
# either None or a value specified by the user. # either None or a value specified by the user.
absolute_tolerance = set_default(self.abs, 1e-12) absolute_tolerance = set_default(self.abs, self.DEFAULT_ABSOLUTE_TOLERANCE)
if absolute_tolerance < 0: if absolute_tolerance < 0:
raise ValueError("absolute tolerance can't be negative: {}".format(absolute_tolerance)) raise ValueError("absolute tolerance can't be negative: {}".format(absolute_tolerance))
@ -241,7 +243,7 @@ class ApproxScalar(ApproxBase):
# we've made sure the user didn't ask for an absolute tolerance only, # we've made sure the user didn't ask for an absolute tolerance only,
# because we don't want to raise errors about the relative tolerance if # because we don't want to raise errors about the relative tolerance if
# we aren't even going to use it. # we aren't even going to use it.
relative_tolerance = set_default(self.rel, 1e-6) * abs(self.expected) relative_tolerance = set_default(self.rel, self.DEFAULT_RELATIVE_TOLERANCE) * abs(self.expected)
if relative_tolerance < 0: if relative_tolerance < 0:
raise ValueError("relative tolerance can't be negative: {}".format(absolute_tolerance)) raise ValueError("relative tolerance can't be negative: {}".format(absolute_tolerance))
@ -252,6 +254,13 @@ class ApproxScalar(ApproxBase):
return max(relative_tolerance, absolute_tolerance) return max(relative_tolerance, absolute_tolerance)
class ApproxDecimal(ApproxScalar):
from decimal import Decimal
DEFAULT_ABSOLUTE_TOLERANCE = Decimal('1e-12')
DEFAULT_RELATIVE_TOLERANCE = Decimal('1e-6')
def approx(expected, rel=None, abs=None, nan_ok=False): def approx(expected, rel=None, abs=None, nan_ok=False):
""" """
Assert that two numbers (or two sets of numbers) are equal to each other Assert that two numbers (or two sets of numbers) are equal to each other
@ -401,6 +410,7 @@ def approx(expected, rel=None, abs=None, nan_ok=False):
from collections import Mapping, Sequence from collections import Mapping, Sequence
from _pytest.compat import STRING_TYPES as String from _pytest.compat import STRING_TYPES as String
from decimal import Decimal
# Delegate the comparison to a class that knows how to deal with the type # Delegate the comparison to a class that knows how to deal with the type
# of the expected value (e.g. int, float, list, dict, numpy.array, etc). # of the expected value (e.g. int, float, list, dict, numpy.array, etc).
@ -422,6 +432,8 @@ def approx(expected, rel=None, abs=None, nan_ok=False):
cls = ApproxMapping cls = ApproxMapping
elif isinstance(expected, Sequence) and not isinstance(expected, String): elif isinstance(expected, Sequence) and not isinstance(expected, String):
cls = ApproxSequence cls = ApproxSequence
elif isinstance(expected, Decimal):
cls = ApproxDecimal
else: else:
cls = ApproxScalar cls = ApproxScalar

View File

@ -0,0 +1 @@
Fix ``TypeError`` issue when using ``approx`` with a ``Decimal`` value.

View File

@ -249,6 +249,7 @@ class TestApprox(object):
(Decimal('-1.000001'), Decimal('-1.0')), (Decimal('-1.000001'), Decimal('-1.0')),
] ]
for a, x in within_1e6: for a, x in within_1e6:
assert a == approx(x)
assert a == approx(x, rel=Decimal('5e-6'), abs=0) assert a == approx(x, rel=Decimal('5e-6'), abs=0)
assert a != approx(x, rel=Decimal('5e-7'), abs=0) assert a != approx(x, rel=Decimal('5e-7'), abs=0)
assert approx(x, rel=Decimal('5e-6'), abs=0) == a assert approx(x, rel=Decimal('5e-6'), abs=0) == a