find(strategy, condition) can be replaced with strategy.filter(condition).example(). It does some other stuff too, but (a) find() is actually not very useful, and (b) it's a messy and these days second-class execution engine compared to @given - see #1609 and in particular #1213.
This is basically a straight clean-up exercise to reduce the API surface that we have to maintain, and ensure that each piece is orthogonal.
I had a look at this and ran into a couple of issues:
example() uses find() under the hood, but unlike find() it only draws the first example. It doesn't do any shrinking behaviour – but we have test helpers like minimal() that make use of that shrinking behaviour. We could inline it twice, but that feels icky.
When I converted find() to use strategy.filter(condition).example() under the hood, I got an error in test_core.py:
hypothesis.errors.InvalidArgument: Cannot call filter on a DataStrategy. You should probably be using @composite for whatever it is you're trying to do.
I don’t have time for more work tonight, but there are two things to think about for the next person to work on this.
Even if we keep using find() internally for a while, deprecating it as a public interface would be a valuable contribution. In practice that would mean moving find() to a non-public namespace, replacing it with a shim that calls note_deprecation and then calls the non-public version, and changing our internal uses to the private version.
Long term we would certainly like to remove it entirely, but the internal changes can happen later.
...turns out that "using find internally" causes a bug in repeated use of .example() for certain strategies:
import hypothesis.strategies as st
strat = st.deferred(
lambda : st.one_of(
st.integers(),
st.dictionaries(st.integers(), strat, min_size=3)
)
)
for i in range(1000):
x = strat.example()
leads to Flaky: Inconsistent test results! Test case was Conclusion(status=Status.VALID, interesting_origin=None) on first run but Conclusion(status=Status.INTERESTING, interesting_origin=None) on second
Implementing find() in terms of @given is pretty easy: https://github.com/HypothesisWorks/hypothesis/compare/master...Zac-HD:deprecate-find
However this is followed by a huge pile of individually-minor but collectively annoying problems, so I'm inclined to switch over the internals and deprecated it so we get the smaller API surface too. Timeline: fairly soon, so the six-month deprecation period allows us to delete it in an early-2020 major version update.
Most helpful comment
Implementing
find()in terms of@givenis pretty easy: https://github.com/HypothesisWorks/hypothesis/compare/master...Zac-HD:deprecate-findHowever this is followed by a huge pile of individually-minor but collectively annoying problems, so I'm inclined to switch over the internals and deprecated it so we get the smaller API surface too. Timeline: fairly soon, so the six-month deprecation period allows us to delete it in an early-2020 major version update.