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