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

Support builds(Optional[MyDataclass]) or document alternative #2930

Closed
ysangkok opened this issue Apr 9, 2021 · 3 comments · Fixed by #2932
Closed

Support builds(Optional[MyDataclass]) or document alternative #2930

ysangkok opened this issue Apr 9, 2021 · 3 comments · Fixed by #2932
Labels
legibility make errors helpful and Hypothesis grokable

Comments

@ysangkok
Copy link

ysangkok commented Apr 9, 2021

>>> import dataclasses
>>> @dataclasses.dataclass
... class A:
...     b: int

Since builds(A) works, I was thinking I can just use builds(Optional[A]), since if A is a type, Optional[A] is also a type.

But it doesn't work:

>>> hypothesis.strategies.builds(Optional[A]).example()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/janus/.pyenv/versions/3.9.1/lib/python3.9/site-packages/hypothesis/strategies/_internal/strategies.py", line 314, in example
    example_generating_inner_function()
  File "/home/janus/.pyenv/versions/3.9.1/lib/python3.9/site-packages/hypothesis/strategies/_internal/strategies.py", line 302, in example_generating_inner_function
    @settings(
  File "/home/janus/.pyenv/versions/3.9.1/lib/python3.9/site-packages/hypothesis/core.py", line 1164, in wrapped_test
    raise the_error_hypothesis_found
  File "/home/janus/.pyenv/versions/3.9.1/lib/python3.9/typing.py", line 664, in __call__
    result = self.__origin__(*args, **kwargs)
  File "/home/janus/.pyenv/versions/3.9.1/lib/python3.9/typing.py", line 329, in __call__
    raise TypeError(f"Cannot instantiate {self!r}")
TypeError: Cannot instantiate typing.Union

It would be nice if it worked, or this use case was documented. I searched in vain for a strategy combinator optional(s: Strategy[A]) -> Strategy[Optional[A]] or something like that, so that I could do optional(builds(A)) and sometimes get a None, sometimes get an A.

@ysangkok
Copy link
Author

ysangkok commented Apr 9, 2021

aaah, you can use from_type!

>>> st.from_type(A)
builds(A)
>>> st.from_type(Optional[A])
one_of(none(), builds(A))

It would be nice if the builds documentation noted that from_type is strictly more capable for dataclasses. What do you think?

@Zac-HD
Copy link
Member

Zac-HD commented Apr 10, 2021

It would be nice if the builds documentation noted that from_type is strictly more capable for dataclasses. What do you think?

It's not though - the real distinction is that st.builds() calls the thing, while st.from_type() gives you instances (possibly by using builds()). On the other hand, you can st.builds(A, b=st.integers(min_value=0) and this is a level of flexibility that st.from_type() doesn't offer (unless you use st.builds() and st.register_type_strategy() first).

I think we could improve the error message when you attempt to build a typing type though, to explain the difference and suggest from_type() instead.

@Zac-HD Zac-HD added the legibility make errors helpful and Hypothesis grokable label Apr 10, 2021
@ysangkok
Copy link
Author

Awesome, thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
legibility make errors helpful and Hypothesis grokable
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants