You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Avoid specialized assert formatting when we detect that __eq__ is overridden #9362
def test_fails():
> assert A(np.array([1,2])) == A(np.array([2,1]))
E assert A(a=array([1, 2])) == A(a=array([2, 1]))
E (pytest_assertion plugin: representation of details failed: .../_pytest/assertion/util.py:430: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().
E Probably an object has a faulty __repr__.)
(Ubuntu 21.10, pytest 6.25, python 3.9)
One way to solve it: since pytest only sees difference on repr perhaps instead of comparing arr1 == arr2 when determining if the fields are different, perhaps it should consider whether repr(arr1) == repr(arr2) which sidesteps the issue with array not returning bool for comparison.
probably the more correct solution here is to avoid pytest's specialized assert formatting when it detects that __eq__ is overridden (since it's not going to accurately represent the underlying equality comparins)
it might also not be a bad idea for pytest to check if its numpy and use the numpy equals there as we do check numpy in a number of places - im under the impression a lot of the numpy handling should get a own plugin module by now
@RonnyPfannschmidt that would create a bug in the other direction in the default case (since dataclass is just going to use == and if we used numpy's comparison then it would be different)
probably the more correct solution here is to avoid pytest's specialized assert formatting when it detects that __eq__ is overridden (since it's not going to accurately represent the underlying equality comparins)
changed the title [-]Numpy arrays in dataclasses fails to introspect[/-][+]Avoid specialized assert formatting when we detect that `__eq__` is overridden[/+]on Dec 3, 2021
it seems to be a little tricky since the method is generated -- one way would maybe be to compare the co_filename of __eq__.__code__ (which appears to be <string> when it's overridden, or whatever the module filename is otherwise)
Running this code under a test will also produce the same problem mentioned in the issue:
left = SimpleDataObject(np.array([1, 2]))
right = SimpleDataObject(np.array([2, 1]))
> assert right == left
E assert SimpleDataObject(a=array([2, 1])) == SimpleDataObject(a=array([1, 2]))
E (pytest_assertion plugin: representation of details failed: c:\users\yuvals\pytest\src\_pytest\assertion\util.py:457: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().
E Probably an object has a faulty __repr__.)
Apart from checking if the dataclass or the attrs.define decorated class (attr.s seems to ignore the customdefined __eq__) has a custom __eq__ method, should we also consider handling attributes which raise an exception during there comparison, something like:
>assertright==leftEAssertionError: assertSimpleDataObject(a=array([2, 1])) ==SimpleDataObject(a=array([1, 2]))
EAttributeswhichraisedanexception:
E ['a']
Or maybe just handle places where the __eq__ method is overridden for this issue?
Activity
asottile commentedon Dec 1, 2021
probably the more correct solution here is to avoid pytest's specialized assert formatting when it detects that
__eq__is overridden (since it's not going to accurately represent the underlying equality comparins)RonnyPfannschmidt commentedon Dec 1, 2021
it might also not be a bad idea for pytest to check if its numpy and use the numpy equals there as we do check numpy in a number of places - im under the impression a lot of the numpy handling should get a own plugin module by now
asottile commentedon Dec 1, 2021
@RonnyPfannschmidt that would create a bug in the other direction in the default case (since
dataclassis just going to use==and if we used numpy's comparison then it would be different)eivindjahren commentedon Dec 2, 2021
This seems like the most robust solution.
[-]Numpy arrays in dataclasses fails to introspect[/-][+]Avoid specialized assert formatting when we detect that `__eq__` is overridden[/+]yuvalshi0 commentedon Dec 7, 2021
@RonnyPfannschmidt I can try to work on this one if anyone haven't yet
yuvalshi0 commentedon Dec 11, 2021
Any tip on how we can determine if the
__eq__method is overridden?I've tried using
__code__attribute but I don't think this is the right directionRonnyPfannschmidt commentedon Dec 11, 2021
off hand, i'm not sure, - @hynek from attrs may have a hint
asottile commentedon Dec 11, 2021
it seems to be a little tricky since the method is generated -- one way would maybe be to compare the
co_filenameof__eq__.__code__(which appears to be<string>when it's overridden, or whatever the module filename is otherwise)hynek commentedon Dec 12, 2021
I remember that @willmcgugan did similar work for rich about detecting if repr was overwritten, so maybe he can help.
yuvalshi0 commentedon Dec 12, 2021
@hynek Thanks!
I think I found it: https://github.com/willmcgugan/rich/blob/07d51ffc1aee6f16bd2e5a25b4e82850fb9ed778/rich/pretty.py#L68
yuvalshi0 commentedon Dec 12, 2021
When I look deeper into the problem, I see it comes in many forms, consider the following code:
Running this code under a test will also produce the same problem mentioned in the issue:
Apart from checking if the
dataclassor theattrs.definedecorated class (attr.sseems to ignore the customdefined__eq__) has a custom__eq__method, should we also consider handling attributes which raise an exception during there comparison, something like:Or maybe just handle places where the
__eq__method is overridden for this issue?hynek commentedon Dec 12, 2021
JFTR attr.s doesn’t ignore a custom eq if auto_detect=True. In attr.define it’s on by default.
I‘m planning on adding an
__attrs_effective_params__(python-attrs/attrs#602) but didn’t get around to it yet. :(yuvalshi0 commentedon Dec 12, 2021
Thanks you the heads up, I'll test that also
Fix numbering and improve changelog entry for pytest-dev#9362
Fix numbering and improve changelog entry for #9362 (#9713)
Merge #33 #34
Merge #33 #34
Merge #29
Merge #33
Merge #128
Merge #35 #36
Merge #31
chore(deps): update dependency pytest to v7 (#3)
Fix numbering and improve changelog entry for pytest-dev#9362 (pytest…
Fix numbering and improve changelog entry for pytest-dev#9362 (pytest…