Skip to content
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

WIP: Merge Bundle as subclass of SampledFromStrategy #4084

Draft
wants to merge 31 commits into
base: master
Choose a base branch
from

Conversation

reaganjlee
Copy link
Contributor

@reaganjlee reaganjlee commented Aug 12, 2024

Seems like the initial values of the states get reversed with the new implementation where e.g.

state.fail_fast(a1=a_5, a2=a_4, a3=a_3, a4=a_2, a5=a_1, a6=a_0, b1=b_2, b2=b_1, b3=b_0) become ...(a1=a_0, a2=a_1, a3=a_2, a4=a_3, a5=a_4, a6=a_5, b1=b_0, b2=b_1, b3=b_2). I'll probably just need to just spend more time looking into the Rule strategy and SampledFromStrategy

Closes #3944

@reaganjlee reaganjlee marked this pull request as draft August 12, 2024 02:51
@reaganjlee reaganjlee force-pushed the consumes branch 2 times, most recently from 6c08dc0 to e2e7f93 Compare August 12, 2024 02:59
@Zac-HD
Copy link
Member

Zac-HD commented Aug 19, 2024

👋 thanks for taking this on Reagan!

Quick note: I generally review PRs when either CI is green, or the contributor explicitly requests a review; happy to do that here too. (although I'll be offline from later this week until early September for a camping trip and thus not reviewing then)

@reaganjlee
Copy link
Contributor Author

Of course and thanks for the note! I'll make a few more attempts at this final test and let you know otherwise. Either way hope you have a good time on your trip!

@reaganjlee
Copy link
Contributor Author

@Zac-HD Mind taking a look to see if it's going in the right direction? Please excuse all the extra prints haha

Copy link
Member

@Zac-HD Zac-HD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks pretty good overall! obviously not done yet, but seems promising 🙂

hypothesis-python/src/hypothesis/stateful.py Outdated Show resolved Hide resolved
@reaganjlee
Copy link
Contributor Author

Don't think I fully understand the logs These lines were always and only run by failing examples? I imagine it's something with the test design, though I can't reproduce locally. Besides that, think everything else is good for review

Copy link
Member

@Zac-HD Zac-HD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgive the somewhat rambly notes, I figured reviewed was better than not 🙂

Overall looks pretty good, though I think it'd be helpful to have a test where we define a consumes bundle which can recursively draw from itself (🤯). The These lines were always and only run by failing examples thing is from Phase.explain; if you disable that in the settings for these tests it'll stop.

Finally, thanks again Reagan - this has turned out to be a lot tricker than I was expecting, and I really appreciate your contribution here! I'm sure many users of stateful testing will agree with me too.

hypothesis-python/src/hypothesis/stateful.py Outdated Show resolved Hide resolved
hypothesis-python/src/hypothesis/stateful.py Outdated Show resolved Hide resolved
hypothesis-python/RELEASE.rst Outdated Show resolved Hide resolved
hypothesis-python/src/hypothesis/stateful.py Outdated Show resolved Hide resolved
Comment on lines 530 to 537
self.elements = bundle
self.reference_to_value = partial(
self.reference_to_val_func, machine.names_to_values
)

ref = super().do_draw(data)
if self.consume:
bundle.remove(ref) # pragma: no cover # coverage is flaky here
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be inclined to restore our placeholder self.elements here.

I'm also wondering what happens if you have a bundle which holds a tree of some kind. Is it possible to get an indexing error from recursive references if something is consumed at the wrong time? I'll need to think about this; we might be fine or we might need something a touch more complicated for consumes bundles...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's also a latent bug here where bundle.remove(ref) can remove a different object to the one we selected, if they're equal, which could be a really subtle problem for someone.

The solution is probably to do elements = range(len(bundle))[::-1] and modify reference_to_val_func to also accept the bundle list and do a two-step lookup + record the index, and finally pop from that index. Ouch.

Comment on lines 559 to 565
res = self.elements[i]
if self.reference_to_value:
value = self.reference_to_value(res)
if self._transform(value) is filter_not_satisfied:
return filter_not_satisfied
return res
return self._transform(res)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we still want to self._transform on line 564, right? So something like

Suggested change
res = self.elements[i]
if self.reference_to_value:
value = self.reference_to_value(res)
if self._transform(value) is filter_not_satisfied:
return filter_not_satisfied
return res
return self._transform(res)
value = self.elements[i]
if self.reference_to_value:
value = self.reference_to_value(value)
return self._transform(value)

Comment on lines 598 to 600
speculative_index = data.draw_integer(
0, max_good_indices - 1, shrink_towards=self.shrink_towards
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... having gone to all this effort to plumb through shrink_towards; I wonder if we actually just want a reverse_elems boolean so that our speculation will efficiently work from the end that we want to shrink to.

Or. Having said that, we could just self.elements = bundle[::-1] in Bundle.do_draw 🤦‍♂️

@reaganjlee
Copy link
Contributor Author

Thanks so much for the fast review! I'll continue editing tomorrow but hope you have a great time on your trip!

@reaganjlee
Copy link
Contributor Author

reaganjlee commented Aug 26, 2024

After taking some time to think about it, I can't seem to make a useful recursive test. Any thoughts here? Maybe a potential use case would be helpful and I can see if I can finish the rest.

Also the last failing tests seems unrelated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support consumes(some_bundle).filter(...) for stateful tests
2 participants