ismatched()   A
last analyzed

Complexity

Conditions 4

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 4
dl 0
loc 10
rs 9.2
1
from hamcrest.core.base_matcher import BaseMatcher
2
from hamcrest.core.helpers.hasmethod import hasmethod
3
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
4
5
__author__ = "Jon Reid"
6
__copyright__ = "Copyright 2011 hamcrest.org"
7
__license__ = "BSD, see License.txt"
8
9
10
class MatchInAnyOrder(object):
11
    def __init__(self, matchers, mismatch_description):
12
        self.matchers = matchers[:]
13
        self.mismatch_description = mismatch_description
14
15
    def matches(self, item):
16
        return self.isnotsurplus(item) and self.ismatched(item)
17
18
    def isfinished(self, sequence):
19
        if not self.matchers:
20
            return True
21
        if self.mismatch_description:
22
            self.mismatch_description.append_text('no item matches: ')      \
23
                                .append_list('', ', ', '', self.matchers)   \
24
                                .append_text(' in ')                        \
25
                                .append_list('[', ', ', ']', sequence)
26
        return False
27
28
    def isnotsurplus(self, item):
29
        if not self.matchers:
30
            if self.mismatch_description:
31
                self.mismatch_description.append_text('not matched: ')  \
32
                                         .append_description_of(item)
33
            return False
34
        return True
35
36
    def ismatched(self, item):
37
        for index, matcher in enumerate(self.matchers):
38
            if matcher.matches(item):
39
                del self.matchers[index]
40
                return True
41
42
        if self.mismatch_description:
43
            self.mismatch_description.append_text('not matched: ')  \
44
                                     .append_description_of(item)
45
        return False
46
47
48
class IsSequenceContainingInAnyOrder(BaseMatcher):
49
50
    def __init__(self, matchers):
51
        self.matchers = matchers
52
53
    def matches(self, sequence, mismatch_description=None):
54
        try:
55
            sequence = list(sequence)
56
            matchsequence = MatchInAnyOrder(self.matchers, mismatch_description)
57
            for item in sequence:
58
                if not matchsequence.matches(item):
59
                    return False
60
            return matchsequence.isfinished(sequence)
61
        except TypeError:
62
            if mismatch_description:
63
                super(IsSequenceContainingInAnyOrder, self)             \
64
                    .describe_mismatch(sequence, mismatch_description)
65
            return False
66
67
    def describe_mismatch(self, item, mismatch_description):
68
        self.matches(item, mismatch_description)
69
70
    def describe_to(self, description):
71
        description.append_text('a sequence over ')             \
72
                   .append_list('[', ', ', ']', self.matchers)  \
73
                   .append_text(' in any order')
74
75
76
def contains_inanyorder(*items):
77
    """Matches if sequences's elements, in any order, satisfy a given list of
78
    matchers.
79
80
    :param match1,...: A comma-separated list of matchers.
81
82
    This matcher iterates the evaluated sequence, seeing if each element
83
    satisfies any of the given matchers. The matchers are tried from left to
84
    right, and when a satisfied matcher is found, it is no longer a candidate
85
    for the remaining elements. If a one-to-one correspondence is established
86
    between elements and matchers, ``contains_inanyorder`` is satisfied.
87
88
    Any argument that is not a matcher is implicitly wrapped in an
89
    :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
90
    equality.
91
92
    """
93
94
    matchers = []
95
    for item in items:
96
        matchers.append(wrap_matcher(item))
97
    return IsSequenceContainingInAnyOrder(matchers)
98