Completed
Pull Request — master (#75)
by Cézar
01:32
created

IsCloseTo.__init__()   A

Complexity

Conditions 3

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
1
import six
2
from hamcrest.core.base_matcher import BaseMatcher
3
from math import fabs
4
5
__author__ = "Jon Reid"
6
__copyright__ = "Copyright 2011 hamcrest.org"
7
__license__ = "BSD, see License.txt"
8
9
10
def isnumeric(value):
11
    """Confirm that 'value' can be treated numerically; duck-test accordingly
12
    """
13
    if isinstance(value, (float, complex) + six.integer_types):
14
        return True
15
16
    try:
17
        _ = (fabs(value) + 0 - 0) * 1
18
        return True
19
    except ArithmeticError:
20
        return True
21
    except:
22
        return False
23
    return False
24
25
26
class IsCloseTo(BaseMatcher):
27
28
    def __init__(self, value, delta):
29
        if not isnumeric(value):
30
            raise TypeError('IsCloseTo value must be numeric')
31
        if not isnumeric(delta):
32
            raise TypeError('IsCloseTo delta must be numeric')
33
34
        self.value = value
35
        self.delta = delta
36
37
    def _matches(self, item):
38
        if not isnumeric(item):
39
            return False
40
        return fabs(item - self.value) <= self.delta
41
42
    def describe_mismatch(self, item, mismatch_description):
43
        if not isnumeric(item):
44
            super(IsCloseTo, self).describe_mismatch(item, mismatch_description)
45
        else:
46
            actual_delta = fabs(item - self.value)
47
            mismatch_description.append_description_of(item)            \
48
                                .append_text(' differed by ')           \
49
                                .append_description_of(actual_delta)
50
51
    def describe_to(self, description):
52
        description.append_text('a numeric value within ')  \
53
                   .append_description_of(self.delta)       \
54
                   .append_text(' of ')                     \
55
                   .append_description_of(self.value)
56
57
58
def close_to(value, delta):
59
    """Matches if object is a number close to a given value, within a given
60
    delta.
61
62
    :param value: The value to compare against as the expected value.
63
    :param delta: The maximum delta between the values for which the numbers
64
        are considered close.
65
66
    This matcher compares the evaluated object against ``value`` to see if the
67
    difference is within a positive ``delta``.
68
69
    Example::
70
71
        close_to(3.0, 0.25)
72
73
    """
74
    return IsCloseTo(value, delta)
75