1
"""Various utility functions."""
2
from collections import namedtuple, OrderedDict
8
def safe_repr(obj, short=False):
12
result = object.__repr__(obj)
13
if not short or len(result) < _MAX_LENGTH:
15
return result[:_MAX_LENGTH] + ' [truncated]...'
19
return "%s.%s" % (cls.__module__, cls.__name__)
21
def sorted_list_difference(expected, actual):
22
"""Finds elements in only one or the other of two, sorted input lists.
24
Returns a two-element tuple of lists. The first list contains those
25
elements in the "expected" list but not in the "actual" list, and the
26
second contains those elements in the "actual" list but not in the
27
"expected" list. Duplicate elements in either input list are ignored.
39
while expected[i] == e:
49
while expected[i] == e:
56
missing.extend(expected[i:])
57
unexpected.extend(actual[j:])
59
return missing, unexpected
62
def unorderable_list_difference(expected, actual, ignore_duplicate=False):
63
"""Same behavior as sorted_list_difference but
64
for lists of unorderable items (like dicts).
66
As it does a linear search per item (remove) it
67
has O(n*n) performance.
78
for lst in expected, actual:
87
unexpected.append(item)
93
return missing, unexpected
95
# anything left in actual is unexpected
96
return missing, actual
98
_Mismatch = namedtuple('Mismatch', 'actual expected value')
100
def _count_diff_all_purpose(actual, expected):
101
'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'
102
# elements need not be hashable
103
s, t = list(actual), list(expected)
104
m, n = len(s), len(t)
107
for i, elem in enumerate(s):
111
for j in range(i, m):
115
for j, other_elem in enumerate(t):
116
if other_elem == elem:
120
diff = _Mismatch(cnt_s, cnt_t, elem)
123
for i, elem in enumerate(t):
127
for j in range(i, n):
131
diff = _Mismatch(0, cnt_t, elem)
135
def _ordered_count(iterable):
136
'Return dict of element counts, in the order they were first seen'
138
for elem in iterable:
139
c[elem] = c.get(elem, 0) + 1
142
def _count_diff_hashable(actual, expected):
143
'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'
144
# elements must be hashable
145
s, t = _ordered_count(actual), _ordered_count(expected)
147
for elem, cnt_s in s.items():
148
cnt_t = t.get(elem, 0)
150
diff = _Mismatch(cnt_s, cnt_t, elem)
152
for elem, cnt_t in t.items():
154
diff = _Mismatch(0, cnt_t, elem)