Repository: HypothesisWorks/hypothesis

Issue:
copying falsifying example into `@example()` fails to reproduce test failure due to pprinter sorting dict keys
Some code depends on the order of dict iteration so sorting the keys before printing makes reproducing a failing test more difficult. 

Related to #2913 ?

**Sample code**:
```
import hypothesis as h
import hypothesis.strategies as st

@h.given(st.dictionaries(st.integers(), st.integers()))
def test(d):
    h.note(f"{d=}")
    assert sorted(d) == list(d)
```

**Output**: falsifying example report gives an input that if copied verbatim, would actually pass the test
```
=========================================================================================== test session starts ===========================================================================================
platform linux -- Python 3.8.11, pytest-5.4.3, py-1.11.0, pluggy-0.13.1
rootdir: [snip]/hypothesis-dictionary-order
plugins: hypothesis-6.47.0
collected 1 item                                                                                                                                                                                          

test.py F                                                                                                                                                                                           [100%]

================================================================================================ FAILURES =================================================================================================
__________________________________________________________________________________________________ test ___________________________________________________________________________________________________

    @h.given(st.dictionaries(st.integers(), st.integers()))
>   def test(d):

test.py:5: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

d = {0: 0, 1: 0}

    @h.given(st.dictionaries(st.integers(), st.integers()))
    def test(d):
        h.note(f"{d=}")
>       assert sorted(d) == list(d)
E       assert [0, 1] == [1, 0]
E         At index 0 diff: 0 != 1
E         Use -v to get the full diff

test.py:7: AssertionError
----------------------------------------------------------------------------------------------- Hypothesis ------------------------------------------------------------------------------------------------
Falsifying example: test(
    d={0: 0, 1: 0},
)
d={1: 0, 0: 0}
========================================================================================= short test summary info =========================================================================================
FAILED test.py::test - assert [0, 1] == [1, 0]
```

**Expected output**: falsifying example should reflect the dict key order as actually passed into the test function


Discussion:
Ooh, thanks for the report - this was OK to do on old versions of Python, but not now that dict iteration order is stable.

Resolving patch:
diff --git a/hypothesis-python/src/hypothesis/vendor/pretty.py b/hypothesis-python/src/hypothesis/vendor/pretty.py
--- a/hypothesis-python/src/hypothesis/vendor/pretty.py
+++ b/hypothesis-python/src/hypothesis/vendor/pretty.py
@@ -603,16 +603,7 @@ def inner(obj, p, cycle):
         if cycle:
             return p.text("{...}")
         p.begin_group(1, start)
-        keys = obj.keys()
-        # if dict isn't large enough to be truncated, sort keys before
-        # displaying
-        if not (p.max_seq_length and len(obj) >= p.max_seq_length):
-            try:
-                keys = sorted(keys)
-            except Exception:
-                # Sometimes the keys don't sort.
-                pass
-        for idx, key in p._enumerate(keys):
+        for idx, key in p._enumerate(obj):
             if idx:
                 p.text(",")
                 p.breakable()


Test patch:
diff --git a/hypothesis-python/tests/cover/test_pretty.py b/hypothesis-python/tests/cover/test_pretty.py
--- a/hypothesis-python/tests/cover/test_pretty.py
+++ b/hypothesis-python/tests/cover/test_pretty.py
@@ -134,6 +134,7 @@ def test_list():
 def test_dict():
     assert pretty.pretty({}) == "{}"
     assert pretty.pretty({1: 1}) == "{1: 1}"
+    assert pretty.pretty({1: 1, 0: 0}) == "{1: 1, 0: 0}"
 
 
 def test_tuple():