Group.equality()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
dl 0
loc 5
rs 9.4285
c 1
b 0
f 1
1
"""Class definitions for compound comparable types."""
2
3
import logging
4
from itertools import permutations
5
6
from comparable.base import CompoundComparable
7
8
9
class Group(CompoundComparable):  # pylint: disable=W0223
10
11
    """Comparable list of Comparable items."""
12
13
    attributes = None  # created dynamically
14
15
    def __init__(self, items):
16
        self.items = items
17
        names = ("item{0}".format(n + 1) for n in range(len(items)))
18
        self.attributes = {name: 1 for name in names}
19
20
    def __repr__(self):
21
        return self._repr(self.items)
22
23
    def __getattr__(self, name):
24
        """Allow self.items[<i>] to be accessed as self.item<i+1>."""
25
        if name.startswith('item'):
26
            try:
27
                index = int(name[4:]) - 1  # "item<n>" -> <n>-1
28
                return self[index]
29
            except ValueError:
30
                logging.debug("%s is not in the form 'item<n>'", name)
31
            except IndexError:
32
                logging.debug("item index %s is out of range", index)
33
34
        raise AttributeError
35
36
    def __len__(self):
37
        return len(self.items)
38
39
    def __getitem__(self, index):
40
        return self.items[index]
41
42
    def equality(self, other):
43
        """Calculate equality based on equality of all group items."""
44
        if not len(self) == len(other):
45
            return False
46
        return super().equality(other)
47
48
    def similarity(self, other):
49
        """Calculate similarity based on best matching permutation of items."""
50
        # Select the longer list as the basis for comparison
51
        if len(self.items) > len(other.items):
52
            first, second = self, other
53
        else:
54
            first, second = other, self
55
        items = list(first.items)  # backup items list
56
        length = len(items)
57
        sim = self.Similarity(0.0 if length else 1.0)
58
59
        # Calculate the similarity for each permutation of items
60
        cname = self.__class__.__name__
61
62
        for num, perm in enumerate(permutations(items, length), start=1):
63
            first.items = perm
64
            aname = 'items-p{}'.format(num)
65
            self.log(first, second, '%', cname=cname, aname=aname)
66
            permutation_sim = super(Group, first).similarity(second)
67
            self.log(first, second, '%', cname=cname, aname=aname,
68
                     result=permutation_sim)
69
70
            sim = max(sim, permutation_sim)
71
            logging.debug("highest similarity: %s", sim)
72
73
        first.items = items  # restore original items list
74
75
        return sim
76