diff --git a/hypothesis-python/src/hypothesis/extra/_patching.py b/hypothesis-python/src/hypothesis/extra/_patching.py index bf973fc81f..933cc9406b 100644 --- a/hypothesis-python/src/hypothesis/extra/_patching.py +++ b/hypothesis-python/src/hypothesis/extra/_patching.py @@ -155,7 +155,7 @@ def get_patch_for(func, failing_examples, *, strip_via=()): # The printed examples might include object reprs which are invalid syntax, # so we parse here and skip over those. If _none_ are valid, there's no patch. call_nodes = [] - for ex, via in failing_examples: + for ex, via in set(failing_examples): with suppress(Exception): node = cst.parse_expression(ex) assert isinstance(node, cst.Call), node diff --git a/hypothesis-python/tests/patching/test_patching.py b/hypothesis-python/tests/patching/test_patching.py index 95ac4622af..2954e159d2 100644 --- a/hypothesis-python/tests/patching/test_patching.py +++ b/hypothesis-python/tests/patching/test_patching.py @@ -147,8 +147,8 @@ def test_make_full_patch(tst, example, expected, body, remove): @pytest.mark.parametrize("n", [0, 1, 2]) def test_invalid_syntax_cases_dropped(n): - tst, example, expected = SIMPLE - example_ls = [example] * n + tst, (ex, via), expected = SIMPLE + example_ls = [(ex.replace("x=1", f"x={x}"), via) for x in range(n)] example_ls.insert(-1, ("fn(\n x=<__main__.Cls object at 0x>,\n)", FAIL_MSG)) got = get_patch_for(tst, example_ls) @@ -158,7 +158,7 @@ def test_invalid_syntax_cases_dropped(n): where, _, after = got assert Path(where) == WHERE - assert after.count(expected.lstrip("+")) == n + assert after.count("@example(x=") == n def test_no_example_for_data_strategy(): @@ -169,6 +169,13 @@ def test_no_example_for_data_strategy(): assert get_patch_for(fn, [("fn(Foo(data=data(...)))", "msg")]) is not None +def test_deduplicates_examples(): + tst, example, expected = SIMPLE + where, _, after = get_patch_for(tst, [example, example]) + assert Path(where) == WHERE + assert after.count(expected.lstrip("+")) == 1 + + def test_irretrievable_callable(): # Check that we return None instead of raising an exception old_module = fn.__module__