Skip to content

Commit

Permalink
recommend @settings if unknown kwarg matches setting name
Browse files Browse the repository at this point in the history
  • Loading branch information
tybug committed Dec 7, 2024
1 parent 90dad4b commit 248a0c1
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
6 changes: 5 additions & 1 deletion hypothesis-python/src/hypothesis/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
HealthCheck,
Phase,
Verbosity,
all_settings,
local_settings,
settings as Settings,
)
Expand Down Expand Up @@ -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.")
Expand Down
26 changes: 26 additions & 0 deletions hypothesis-python/tests/cover/test_given_error_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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"]()

0 comments on commit 248a0c1

Please sign in to comment.