From 248a0c11a3731609c3d8490d192b580041e1f76b Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Sat, 7 Dec 2024 02:30:06 -0500 Subject: [PATCH] recommend @settings if unknown kwarg matches setting name --- hypothesis-python/src/hypothesis/core.py | 6 ++++- .../cover/test_given_error_conditions.py | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/hypothesis-python/src/hypothesis/core.py b/hypothesis-python/src/hypothesis/core.py index 34a274a6ea..d60fcab01f 100644 --- a/hypothesis-python/src/hypothesis/core.py +++ b/hypothesis-python/src/hypothesis/core.py @@ -45,6 +45,7 @@ HealthCheck, Phase, Verbosity, + all_settings, local_settings, settings as Settings, ) @@ -405,9 +406,12 @@ def is_invalid_test(test, original_sig, given_arguments, given_kwargs): ] if extra_kwargs and (params == [] or params[-1].kind is not params[-1].VAR_KEYWORD): arg = extra_kwargs[0] + extra = "" + if arg in all_settings: + extra = f". Did you mean @settings({arg}={given_kwargs[arg]!r})?" return invalid( f"{test.__name__}() got an unexpected keyword argument {arg!r}, " - f"from `{arg}={given_kwargs[arg]!r}` in @given" + f"from `{arg}={given_kwargs[arg]!r}` in @given{extra}" ) if any(p.default is not p.empty for p in params): return invalid("Cannot apply @given to a function with defaults.") diff --git a/hypothesis-python/tests/cover/test_given_error_conditions.py b/hypothesis-python/tests/cover/test_given_error_conditions.py index e417a6fc1a..fe1c3ff396 100644 --- a/hypothesis-python/tests/cover/test_given_error_conditions.py +++ b/hypothesis-python/tests/cover/test_given_error_conditions.py @@ -11,6 +11,7 @@ import pytest from hypothesis import assume, given, reject, settings +from hypothesis._settings import all_settings from hypothesis.errors import InvalidArgument, Unsatisfiable from hypothesis.strategies import booleans, integers, nothing @@ -112,3 +113,28 @@ async def foo(x): match="Hypothesis doesn't know how to run async test functions", ): foo() + + +@pytest.mark.parametrize("setting_name", all_settings.keys()) +def test_suggests_at_settings_if_extra_kwarg_matches_setting_name(setting_name): + val = 1 + + # dynamically create functions with an extra kwarg argument which happens to + # match a settings variable. The user probably meant @settings. + # exec is pretty cursed here, but it does work. + namespace = {} + exec( + f""" +@given(a=1, {setting_name}={val}) +def foo(a): + pass + """, + globals(), + namespace, + ) + + with pytest.raises( + InvalidArgument, + match=rf"Did you mean @settings\({setting_name}={val}\)\?", + ): + namespace["foo"]()