comparison CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/unittest/util.py @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
comparison
equal deleted inserted replaced
67:0e9998148a16 69:33d812a61356
1 """Various utility functions."""
2
3 from collections import namedtuple, Counter
4 from os.path import commonprefix
5
6 __unittest = True
7
8 _MAX_LENGTH = 80
9 _PLACEHOLDER_LEN = 12
10 _MIN_BEGIN_LEN = 5
11 _MIN_END_LEN = 5
12 _MIN_COMMON_LEN = 5
13 _MIN_DIFF_LEN = _MAX_LENGTH - \
14 (_MIN_BEGIN_LEN + _PLACEHOLDER_LEN + _MIN_COMMON_LEN +
15 _PLACEHOLDER_LEN + _MIN_END_LEN)
16 assert _MIN_DIFF_LEN >= 0
17
18 def _shorten(s, prefixlen, suffixlen):
19 skip = len(s) - prefixlen - suffixlen
20 if skip > _PLACEHOLDER_LEN:
21 s = '%s[%d chars]%s' % (s[:prefixlen], skip, s[len(s) - suffixlen:])
22 return s
23
24 def _common_shorten_repr(*args):
25 args = tuple(map(safe_repr, args))
26 maxlen = max(map(len, args))
27 if maxlen <= _MAX_LENGTH:
28 return args
29
30 prefix = commonprefix(args)
31 prefixlen = len(prefix)
32
33 common_len = _MAX_LENGTH - \
34 (maxlen - prefixlen + _MIN_BEGIN_LEN + _PLACEHOLDER_LEN)
35 if common_len > _MIN_COMMON_LEN:
36 assert _MIN_BEGIN_LEN + _PLACEHOLDER_LEN + _MIN_COMMON_LEN + \
37 (maxlen - prefixlen) < _MAX_LENGTH
38 prefix = _shorten(prefix, _MIN_BEGIN_LEN, common_len)
39 return tuple(prefix + s[prefixlen:] for s in args)
40
41 prefix = _shorten(prefix, _MIN_BEGIN_LEN, _MIN_COMMON_LEN)
42 return tuple(prefix + _shorten(s[prefixlen:], _MIN_DIFF_LEN, _MIN_END_LEN)
43 for s in args)
44
45 def safe_repr(obj, short=False):
46 try:
47 result = repr(obj)
48 except Exception:
49 result = object.__repr__(obj)
50 if not short or len(result) < _MAX_LENGTH:
51 return result
52 return result[:_MAX_LENGTH] + ' [truncated]...'
53
54 def strclass(cls):
55 return "%s.%s" % (cls.__module__, cls.__qualname__)
56
57 def sorted_list_difference(expected, actual):
58 """Finds elements in only one or the other of two, sorted input lists.
59
60 Returns a two-element tuple of lists. The first list contains those
61 elements in the "expected" list but not in the "actual" list, and the
62 second contains those elements in the "actual" list but not in the
63 "expected" list. Duplicate elements in either input list are ignored.
64 """
65 i = j = 0
66 missing = []
67 unexpected = []
68 while True:
69 try:
70 e = expected[i]
71 a = actual[j]
72 if e < a:
73 missing.append(e)
74 i += 1
75 while expected[i] == e:
76 i += 1
77 elif e > a:
78 unexpected.append(a)
79 j += 1
80 while actual[j] == a:
81 j += 1
82 else:
83 i += 1
84 try:
85 while expected[i] == e:
86 i += 1
87 finally:
88 j += 1
89 while actual[j] == a:
90 j += 1
91 except IndexError:
92 missing.extend(expected[i:])
93 unexpected.extend(actual[j:])
94 break
95 return missing, unexpected
96
97
98 def unorderable_list_difference(expected, actual):
99 """Same behavior as sorted_list_difference but
100 for lists of unorderable items (like dicts).
101
102 As it does a linear search per item (remove) it
103 has O(n*n) performance."""
104 missing = []
105 while expected:
106 item = expected.pop()
107 try:
108 actual.remove(item)
109 except ValueError:
110 missing.append(item)
111
112 # anything left in actual is unexpected
113 return missing, actual
114
115 def three_way_cmp(x, y):
116 """Return -1 if x < y, 0 if x == y and 1 if x > y"""
117 return (x > y) - (x < y)
118
119 _Mismatch = namedtuple('Mismatch', 'actual expected value')
120
121 def _count_diff_all_purpose(actual, expected):
122 'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'
123 # elements need not be hashable
124 s, t = list(actual), list(expected)
125 m, n = len(s), len(t)
126 NULL = object()
127 result = []
128 for i, elem in enumerate(s):
129 if elem is NULL:
130 continue
131 cnt_s = cnt_t = 0
132 for j in range(i, m):
133 if s[j] == elem:
134 cnt_s += 1
135 s[j] = NULL
136 for j, other_elem in enumerate(t):
137 if other_elem == elem:
138 cnt_t += 1
139 t[j] = NULL
140 if cnt_s != cnt_t:
141 diff = _Mismatch(cnt_s, cnt_t, elem)
142 result.append(diff)
143
144 for i, elem in enumerate(t):
145 if elem is NULL:
146 continue
147 cnt_t = 0
148 for j in range(i, n):
149 if t[j] == elem:
150 cnt_t += 1
151 t[j] = NULL
152 diff = _Mismatch(0, cnt_t, elem)
153 result.append(diff)
154 return result
155
156 def _count_diff_hashable(actual, expected):
157 'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'
158 # elements must be hashable
159 s, t = Counter(actual), Counter(expected)
160 result = []
161 for elem, cnt_s in s.items():
162 cnt_t = t.get(elem, 0)
163 if cnt_s != cnt_t:
164 diff = _Mismatch(cnt_s, cnt_t, elem)
165 result.append(diff)
166 for elem, cnt_t in t.items():
167 if elem not in s:
168 diff = _Mismatch(0, cnt_t, elem)
169 result.append(diff)
170 return result