-
Notifications
You must be signed in to change notification settings - Fork 586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
clarify docs on Bundles vs. instance variables #3511
Comments
|
I agree that docs clarifying this would be really helpful! My understanding so far: The situation in which Bundles are strictly more powerful is that Bundles can be used in place of strategies to generate inputs to rules. Thus, for instance, one can use a rule to build up a pool of examples in a Bundle, and then other rules can draw from that population of Bundles. For dictionaries, for example, the Bundles of keys/values serve as a universe to draw from, so that rules looking up things have a decent chance of selecting things that have already been inserted. While I'm not sure how you can do this with instance variables: the strategies that generate inputs to rules have no access to the current state of the state machine. This might be resolvable by adding a function to hypothesis (something like flatmap that calls a user-provided function that takes as its argument the current machine state), or it might be a fundamental limit designed in to the example generation/simplification process. My guess is that Bundles are an attempt to provide this ability. I do have at least one question about how bundles work: the documentation states that a |
As in @jab's example, you can use Bundles are "just" an interface which allows you to express this pattern somewhat more compactly, and ideally clearly, especially once you get to something like
That design choice actually predates my involvement in the project by a few years (!!), but it does seem that we're missing a primitive here - you can easily combine elements from two bundles into one, but not vice-versa. Perhaps something we should consider adding, like we added |
|
Is it then untrue that Bundles are strictly more powerful?
Would a PR clarifying the docs be welcome? Even if the PR needed review to be sure I had properly understood? |
|
Oops, yes, those docs are just plain wrong! (I think they were correct when written, before Hypothesis 3.0 added good support for interactive data) PRs definitely welcome 😍 If interested, you can read a bit about our PR review philosophy here. |
Trying to address this, I find the following in the documentation:
The phrases "at most once" and "in any order" would appear to be in conflict with each other. They also conflict with the function's own documentation:
The code (in My understanding is:
Is this about right? For now I'll make the rest of the docs match the implementation. |
I realise that more primitives are not a good thing, but it seems like a clean functional way to avoid the need to sue @rule(x=with_state(lambda self: st.sampled_from(self.not_a_bundle)))
def f(self, x):
...This would seem to allow the same operations as bundles, with minimal extra ceremony, and without requiring users to learn a new data type/interface. But I don't know whether it would allow hypothesis to reason about/shrink/manipulate examples as effectively - with Bundles the dependence on state is more explicit, in that hypothesis knows exactly which rules may change the contents of a bundle (usually few). If Bundles are container classes, do they have any properties that should be described? Can a Bundle contain the same value twice? (relevant with |
|
Bundles can contain duplicate values, and are essentially lists/sampled_from under the hood. Since |
Actually, that's pretty much what I was hoping for. Will this support explicit example generation (the way |
|
@td-anne, your changes look great, thanks so much! |
I read through the https://hypothesis.readthedocs.io/en/latest/stateful.html docs several times, and am still having trouble understanding when you would use Bundles vs. instance variables. The docs say:
But I'm not seeing what you can do with Bundles that you can't do with instance variables because they're not powerful enough.
For example, in https://github.com/jab/lfu-cache/blob/main/test_lfu.py I was able to use only instance variables to test several properties of an LFU cache, and I feel like plain old instance variables alone are getting me really far. Is there anything I'm missing out on by not using Bundles?
I noticed the docs also add:
Given that limitation, it's even less clear to me when it's worth it to use Bundles.
I also had a similar question on when to use a plain old
__init__method (as in the docs'DatabaseComparisonexample) vs.initializesthat I might as well mention here too. The answer I would have guessed is that@initializeallows you to take in some strategy-generated input as an argument, while__init__does not. But the docs don't say that, and I'm not sure it's actually true. Perhaps a section on "when to use__init__vs.@initializewould help clarify that too.)Thanks!
The text was updated successfully, but these errors were encountered: