annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/unittest/util.py @ 68:5028fdace37b

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