-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Fix unguarded ==
comparison in fixtures.
#6541
Fix unguarded ==
comparison in fixtures.
#6541
Conversation
src/_pytest/fixtures.py
Outdated
try: | ||
cache_valid = bool(my_cache_key == cache_key) | ||
except (TypeError, ValueError): | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should warn that a fragile cache key was used,
pytest should at some point require parameters to be reasonably stable/hash-able
accidentally and strangely modifiable parameters have led to many horrendous errors as aftermath of accidential modification
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll add a warning.
Regarding the TypeError
case, is that even desirable? Classes have to actively disallow ==
, if unimplemented it defaults to is
, which would be okay. Should we consider a class that raises TypeError
on __eq__
as pathological? Besides, AttributeError
would also be an option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should straight out error out instead? Warnings have a tendency to get ignored, and we should avoid letting users running test suites with problematic setups.
So I suggest we raise an appropriate error pointing to the problematic node id instead.
Regarding the TypeError case
We should actually handle any exception I think (using Exception
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for clarity, @nicoddemus do you mean to also error out in the NumPy array case? After thinking about it for a second, I agree that's the most reasonable solution. Besides brittleness, another reason is that every ==
operation with an array computes a new boolean array, so with large arrays as parameters, the comparisons can get quite expensive.
I suggest to include a hint in the error message to use scope='function'
for NumPy arrays or other types where if a == b:
can raise an exception. The docs would ideally also mention that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for clarity, @nicoddemus do you mean to also error out in the NumPy array case? After thinking about it for a second, I agree that's the most reasonable solution. Besides brittleness, another reason is that every == operation with an array computes a new boolean array, so with large arrays as parameters, the comparisons can get quite expensive.
Yes that's my reasoning as well: we should straight out discourage parametrization using types that don't have standard/buggy ==
operators.
I suggest to include a hint in the error message to use scope='function' for NumPy arrays or other types where if a == b: can raise an exception. The docs would ideally also mention that case.
Not sure, this problem is not related to scoping at all, I'm afraid. We could however add a link in the exception message to a section in the docs where this is explained, probably using numpy
arrays as example and possible workarounds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @RonnyPfannschmidt those are good points.
I'm still leaning towards just breaking it in the next feature release though (don't think this will affect many users), but I'm also OK about deprecating it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw, please get the final word then so @kohr-h can finish the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if we did something more clever with request.param
below in def cache_key
-- I think we could probably use object identity (id(...)
) for request.param
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we remove support for them it breaks test-suites that are technically working
Hm, with the current release test suites are already broken, so the question is whether you prefer to add a (somewhat dirty) workaround or rather keep failing, but with a better error message. Or would it make sense to re-enable a broken feature and deprecate it at the same time?
@asottile You mean replace ==
with is
basically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quick testing shows that is
instead of ==
could work. I'll do a push and see how the test suite does.
fb3975f
to
f0fd818
Compare
Works with |
Maybe around here? pytest/testing/python/fixtures.py Line 1105 in 2c32dad
|
Now with test. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @kohr-h!
Pushed minor improvements and fixed linting.
As we only use the comparison for caching, I don't think this will have any adverse effects. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, looks good.
Please squash it though (@nicoddemus can do it).
Just did, thanks for catching it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please squash it though (@nicoddemus can do it).
Just did, thanks for catching it.
Has not been done/pushed?
JFI: I'm out of here (given the animated GIF).
4de0aa6
to
80d4dd6
Compare
My bad, done. 😅 |
Ah, just saw that this is merged, 👍 -- and that the conversation took a funny turn.. |
The fix for Issue pytest-dev#6541 caused regression where cache hits became cache misses, unexpectedly. Attempt to restore the previous behavior, while also retaining the fix for the bug. Fixes: Issue pytest-dev#6962
The fix for Issue pytest-dev#6541 caused regression where cache hits became cache misses, unexpectedly. Attempt to restore the previous behavior, while also retaining the fix for the bug. Fixes: Issue pytest-dev#6962
The fix for Issue pytest-dev#6541 caused regression where cache hits became cache misses, unexpectedly. Attempt to restore the previous behavior, while also retaining the fix for the bug. Fixes: Issue pytest-dev#6962
The fix for Issue pytest-dev#6541 caused regression where cache hits became cache misses, unexpectedly. Attempt to restore the previous behavior, while also retaining the fix for the bug. Fixes: Issue pytest-dev#6962
The fix for Issue pytest-dev#6541 caused regression where cache hits became cache misses, unexpectedly. Attempt to restore the previous behavior, while also retaining the fix for the bug. Fixes: Issue pytest-dev#6962
The fix for Issue pytest-dev#6541 caused regression where cache hits became cache misses, unexpectedly. Attempt to restore the previous behavior, while also retaining the fix for the bug. Fixes: Issue pytest-dev#6962
The fix for Issue #6541 caused regression where cache hits became cache misses, unexpectedly. Fixes #6962 --------- Co-authored-by: Nicolas Simonds <[email protected]> Co-authored-by: Bruno Oliveira <[email protected]> Co-authored-by: Ran Benita <[email protected]>
The fix for Issue pytest-dev#6541 caused regression where cache hits became cache misses, unexpectedly. Fixes pytest-dev#6962 --------- Co-authored-by: Nicolas Simonds <[email protected]> Co-authored-by: Bruno Oliveira <[email protected]> Co-authored-by: Ran Benita <[email protected]>
Here's an attempt to fix the equality checking issue in fixtures.
To do:
Closes: #6497