diff --git a/AUTHORS b/AUTHORS index bb5fec0d6..be4cd290d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -24,6 +24,7 @@ Daniel Grana Daniel Nuri Dave Hunt David Mohr +Edison Gustavo Muenz Floris Bruynooghe Graham Horler Grig Gheorghiu diff --git a/CHANGELOG b/CHANGELOG index 052454d2f..c2ac4bfa3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,9 @@ - fix issue748: unittest.SkipTest reports to internal pytest unittest plugin. Thanks Thomas De Schampheleire for reporting and Bruno Oliveira for the PR. +- fix issue718: failed to create representation of sets containing unsortable + elements in python 2. Thanks Edison Gustavo Muenz + 2.7.1 (compared to 2.7.0) ----------------------------- diff --git a/_pytest/assertion/util.py b/_pytest/assertion/util.py index 07389e781..fb5f9be0e 100644 --- a/_pytest/assertion/util.py +++ b/_pytest/assertion/util.py @@ -225,10 +225,18 @@ def _compare_eq_iterable(left, right, verbose=False): # dynamic import to speedup pytest import difflib - left = pprint.pformat(left).splitlines() - right = pprint.pformat(right).splitlines() - explanation = [u('Full diff:')] - explanation.extend(line.strip() for line in difflib.ndiff(left, right)) + try: + left_formatting = pprint.pformat(left).splitlines() + right_formatting = pprint.pformat(right).splitlines() + explanation = [u('Full diff:')] + except Exception: + # hack: PrettyPrinter.pformat() in python 2 fails when formatting items that can't be sorted(), ie, calling + # sorted() on a list would raise. See issue #718. + # As a workaround, the full diff is generated by using the repr() string of each item of each container. + left_formatting = sorted(repr(x) for x in left) + right_formatting = sorted(repr(x) for x in right) + explanation = [u('Full diff (fallback to calling repr on each item):')] + explanation.extend(line.strip() for line in difflib.ndiff(left_formatting, right_formatting)) return explanation diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 1cf00dfed..e8063f0d3 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -569,3 +569,39 @@ def test_AssertionError_message(testdir): *assert 0, (x,y)* *AssertionError: (1, 2)* """) + +@pytest.mark.skipif(PY3, reason='This bug does not exist on PY3') +def test_set_with_unsortable_elements(): + # issue #718 + class UnsortableKey(object): + def __init__(self, name): + self.name = name + + def __lt__(self, other): + raise RuntimeError() + + def __repr__(self): + return 'repr({0})'.format(self.name) + + def __eq__(self, other): + return self.name == other.name + + def __hash__(self): + return hash(self.name) + + left_set = set(UnsortableKey(str(i)) for i in range(1, 3)) + right_set = set(UnsortableKey(str(i)) for i in range(2, 4)) + expl = callequal(left_set, right_set, verbose=True) + # skip first line because it contains the "construction" of the set, which does not have a guaranteed order + expl = expl[1:] + dedent = textwrap.dedent(""" + Extra items in the left set: + repr(1) + Extra items in the right set: + repr(3) + Full diff (fallback to calling repr on each item): + - repr(1) + repr(2) + + repr(3) + """).strip() + assert '\n'.join(expl) == dedent