Skip to content

Commit

Permalink
add warning all elements to sampled_from are strategies, suggestive o…
Browse files Browse the repository at this point in the history
…f one_of; close HypothesisWorks#3819
  • Loading branch information
vreuter committed Dec 22, 2023
1 parent 6a6c1cf commit 4880b11
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 9 deletions.
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ their individual contributions.
* `Tyler Gibbons <https://www.github.com/kavec>`_ ([email protected])
* `Tyler Nickerson <https://www.github.com/nmbrgts>`_
* `Vidya Rani <https://www.github.com/vidyarani-dg>`_ ([email protected])
* `Vince Reuter <https://github.com/vreuter>`_ ([email protected])
* `Vincent Michel <https://www.github.com/vxgmichel>`_ ([email protected])
* `Viorel Pluta <https://github.com/viopl>`_ ([email protected])
* `Vytautas Strimaitis <https://www.github.com/vstrimaitis>`_
Expand Down
4 changes: 4 additions & 0 deletions hypothesis-python/src/hypothesis/strategies/_internal/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ def sampled_from(
"so maybe you tried to write an enum as if it was a dataclass?"
)
raise InvalidArgument("Cannot sample from a length-zero sequence.")
elif all(isinstance(x, SearchStrategy) for x in values):
warnings.warn(
"sample_from was given a collection of strategies; was one_of intended?"
)
if len(values) == 1:
return just(values[0])
try:
Expand Down
26 changes: 17 additions & 9 deletions hypothesis-python/tests/cover/test_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,21 +311,29 @@ class Baz(Foo):


@pytest.mark.parametrize(
"var,expected",
"var,expected,exp_warn",
[
(typing.TypeVar("V"), object),
(typing.TypeVar("V", bound=int), int),
(typing.TypeVar("V", bound=Foo), (Bar, Baz)),
(typing.TypeVar("V", bound=typing.Union[int, str]), (int, str)),
(typing.TypeVar("V", int, str), (int, str)),
# Expect a warning exactly when the type constraint/bound should trigger
# passing a strategy to sampled_from.
(typing.TypeVar("V"), object, False),
(typing.TypeVar("V", bound=int), int, False),
(typing.TypeVar("V", bound=Foo), (Bar, Baz), True),
(typing.TypeVar("V", bound=typing.Union[int, str]), (int, str), True),
(typing.TypeVar("V", int, str), (int, str), False),
],
)
@settings(suppress_health_check=[HealthCheck.too_slow])
@given(data=st.data())
def test_typevar_type_is_consistent(data, var, expected):
def test_typevar_type_is_consistent(data, var, expected, exp_warn):
strat = st.from_type(var)
v1 = data.draw(strat)
v2 = data.draw(strat)
if exp_warn:
with warnings.catch_warnings:
warnings.filterwarnings(action="ignore", category=UserWarning)
v1 = data.draw(strat)
v2 = data.draw(strat)
else:
v1 = data.draw(strat)
v2 = data.draw(strat)
assume(v1 != v2) # Values may vary, just not types
assert type(v1) == type(v2)
assert isinstance(v1, expected)
Expand Down
10 changes: 10 additions & 0 deletions hypothesis-python/tests/cover/test_sampled_from.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,13 @@ class AnnotationsInsteadOfElements(enum.Enum):
def test_suggests_elements_instead_of_annotations():
with pytest.raises(InvalidArgument, match="Cannot sample.*annotations.*dataclass"):
st.sampled_from(AnnotationsInsteadOfElements).example()


@pytest.mark.parametrize("wrap", [list, tuple])
def test_warns_when_given_entirely_strategies_as_elements(wrap):
elements = wrap([st.booleans(), st.decimals(), st.integers(), st.text()])
with pytest.warns(
UserWarning,
match="sample_from was given a collection of strategies; was one_of intended?",
):
st.sampled_from(elements)

0 comments on commit 4880b11

Please sign in to comment.