+++ /dev/null
-"""Various utility functions."""\r
-from collections import namedtuple, OrderedDict\r
-\r
-\r
-__unittest = True\r
-\r
-_MAX_LENGTH = 80\r
-def safe_repr(obj, short=False):\r
- try:\r
- result = repr(obj)\r
- except Exception:\r
- result = object.__repr__(obj)\r
- if not short or len(result) < _MAX_LENGTH:\r
- return result\r
- return result[:_MAX_LENGTH] + ' [truncated]...'\r
-\r
-\r
-def strclass(cls):\r
- return "%s.%s" % (cls.__module__, cls.__name__)\r
-\r
-def sorted_list_difference(expected, actual):\r
- """Finds elements in only one or the other of two, sorted input lists.\r
-\r
- Returns a two-element tuple of lists. The first list contains those\r
- elements in the "expected" list but not in the "actual" list, and the\r
- second contains those elements in the "actual" list but not in the\r
- "expected" list. Duplicate elements in either input list are ignored.\r
- """\r
- i = j = 0\r
- missing = []\r
- unexpected = []\r
- while True:\r
- try:\r
- e = expected[i]\r
- a = actual[j]\r
- if e < a:\r
- missing.append(e)\r
- i += 1\r
- while expected[i] == e:\r
- i += 1\r
- elif e > a:\r
- unexpected.append(a)\r
- j += 1\r
- while actual[j] == a:\r
- j += 1\r
- else:\r
- i += 1\r
- try:\r
- while expected[i] == e:\r
- i += 1\r
- finally:\r
- j += 1\r
- while actual[j] == a:\r
- j += 1\r
- except IndexError:\r
- missing.extend(expected[i:])\r
- unexpected.extend(actual[j:])\r
- break\r
- return missing, unexpected\r
-\r
-\r
-def unorderable_list_difference(expected, actual, ignore_duplicate=False):\r
- """Same behavior as sorted_list_difference but\r
- for lists of unorderable items (like dicts).\r
-\r
- As it does a linear search per item (remove) it\r
- has O(n*n) performance.\r
- """\r
- missing = []\r
- unexpected = []\r
- while expected:\r
- item = expected.pop()\r
- try:\r
- actual.remove(item)\r
- except ValueError:\r
- missing.append(item)\r
- if ignore_duplicate:\r
- for lst in expected, actual:\r
- try:\r
- while True:\r
- lst.remove(item)\r
- except ValueError:\r
- pass\r
- if ignore_duplicate:\r
- while actual:\r
- item = actual.pop()\r
- unexpected.append(item)\r
- try:\r
- while True:\r
- actual.remove(item)\r
- except ValueError:\r
- pass\r
- return missing, unexpected\r
-\r
- # anything left in actual is unexpected\r
- return missing, actual\r
-\r
-_Mismatch = namedtuple('Mismatch', 'actual expected value')\r
-\r
-def _count_diff_all_purpose(actual, expected):\r
- 'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'\r
- # elements need not be hashable\r
- s, t = list(actual), list(expected)\r
- m, n = len(s), len(t)\r
- NULL = object()\r
- result = []\r
- for i, elem in enumerate(s):\r
- if elem is NULL:\r
- continue\r
- cnt_s = cnt_t = 0\r
- for j in range(i, m):\r
- if s[j] == elem:\r
- cnt_s += 1\r
- s[j] = NULL\r
- for j, other_elem in enumerate(t):\r
- if other_elem == elem:\r
- cnt_t += 1\r
- t[j] = NULL\r
- if cnt_s != cnt_t:\r
- diff = _Mismatch(cnt_s, cnt_t, elem)\r
- result.append(diff)\r
-\r
- for i, elem in enumerate(t):\r
- if elem is NULL:\r
- continue\r
- cnt_t = 0\r
- for j in range(i, n):\r
- if t[j] == elem:\r
- cnt_t += 1\r
- t[j] = NULL\r
- diff = _Mismatch(0, cnt_t, elem)\r
- result.append(diff)\r
- return result\r
-\r
-def _ordered_count(iterable):\r
- 'Return dict of element counts, in the order they were first seen'\r
- c = OrderedDict()\r
- for elem in iterable:\r
- c[elem] = c.get(elem, 0) + 1\r
- return c\r
-\r
-def _count_diff_hashable(actual, expected):\r
- 'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'\r
- # elements must be hashable\r
- s, t = _ordered_count(actual), _ordered_count(expected)\r
- result = []\r
- for elem, cnt_s in s.items():\r
- cnt_t = t.get(elem, 0)\r
- if cnt_s != cnt_t:\r
- diff = _Mismatch(cnt_s, cnt_t, elem)\r
- result.append(diff)\r
- for elem, cnt_t in t.items():\r
- if elem not in s:\r
- diff = _Mismatch(0, cnt_t, elem)\r
- result.append(diff)\r
- return result\r