-
-
Notifications
You must be signed in to change notification settings - Fork 12k
MAINT: move comparison operator special-handling out of ufunc parsing. #11282
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
Conversation
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.
I tried using the seemingly more logical PyArray_FromAny(other, NULL, 0, 0, 0, NULL) but somehow this returns a failure when other is a python string.
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.
You probably need to PyErr_Fetch above, before you start calling any more functions - most python functions are not willing to run if an exception is actively being thrown
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.
Ah, yes, that indeed does it!
|
This presumably means |
|
@eric-wieser - yes, indeed, the ufuncs themselves will no longer return |
|
Can you add some tests for ufuncs no longer returning NotImplemented? |
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.
Maybe better to just add a PyObject *warning_type argument to the original function, and use PyErr_WarnEx(warning_type, msg, 1) in place of DEPRECATE_FUTUREWARNING
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.
Since I needed the fetch the error anyway, the need for the new function disappeared...
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.
typo
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.
weird indent
|
It would be nice even at this early stage to document the user-visible changes and change the tests appropriately |
c49d901 to
c8dffb2
Compare
|
OK, now simpler with @mattip - agreed about documentation, but there isn't even a file for the 1.16 release notes yet... But the main effect is the one @eric-wieser noted: now the |
|
Just to emphasize, do not merge before the 1.15 branch. |
c8dffb2 to
61bd834
Compare
|
OK, tests now all pass - further review much appreciated! |
61bd834 to
72bab23
Compare
|
Rebased, so now this is just a single commit. |
72bab23 to
f7029ce
Compare
|
With 1.15 branches, I rebased this and added a release note for 1.16. If everyone is still happy with this, it would be nice to merge it, since I have other changes to the ufunc parsing in the pipeline (#11333 in particular). |
|
@mattip, @eric-wieser - any further comments on this? |
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.
Would be clearer if other_is_flexible and ndim_other were assigned in this path, rather than initialized.
The argument parsing for ufuncs contains special logic to enable returning NotImplemented for comparison functions. The ufuncs, however, should not have to know whether they were called via a python comparison operator, so this PR moves the logic to the operators, checking after ufunc failed whether a NotImplemented should be returned.
f7029ce to
13c42ef
Compare
|
OK, thanks, did all three. |
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.
I think this should
- Appear before the
DEPRECATE_FUTUREWARNINGline - say
placeholder warning, not placeholder error.
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.
It is just that if the deprecation is removed, the chained exception should be replaced (I wanted to have code that would at least work, but didn't feel like creating the array now...). I clarified this.
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.
I'd say that's obvious, in the same way that the return NULL should also be replaced
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.
Can you extract the contents of this long if to _failed_compare_workaround(self, other, op), or something similar (documented to expect an exception to already be in flight)
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.
Done.
|
OK, pushed an extra commit moving the failure path to its own function. |
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.
Date and version comment needed
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.
Date and version comment needed
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.
Date and version comment needed
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.
I think it would be tidy to move this to a fail: label
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 could also be the fail label - PyArray_ChainExceptionsCause is a shorhand for PyErr_Restore if no exception is set.
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.
Yes, this makes a lot more sense.
8574044 to
a2b9baa
Compare
|
@mattip, @eric-wieser - all implemented. |
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 line should be the ChainExceptions, not PyErr_Restore. The former implies the latter, not vice versa
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.
A comment here saying "Reraise the original exception, or chain the new one" might be nice too
doc/release/1.16.0-notes.rst
Outdated
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.
"such as np.equal" might be helpful here.
doc/release/1.16.0-notes.rst
Outdated
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.
Can you point out that the comparison operators continue to return NotImplemented as before?
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 just "when this warning is removed, it should return a correctly-shaped array of bool.
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.
I'd probably add an else { goto fail; } here, just to have somewhere obvious to tie the comment to. The compiler should optimize it just the same anyway
a2b9baa to
533bb37
Compare
|
@eric-wieser - thanks for the further comments; all done. |
eric-wieser
left a comment
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.
Implementation looks good now.
Did you just cut up the original long comment, or did you throw it out and reword it? I haven't yet checked to see if all of the important bits survived.
|
Yes, I reworded the long comment, removing parts not relevant for comparison operators. I think it now (even) more clearly states where we want to go. |
|
As this was approved, I'll go ahead and merge so I can can rebase some of the other PRs (which will be easier to look at without the long distracting stuff in |
| } | ||
| else { | ||
| /* LE, LT, GT, or GE with non-flexible other; just pass on error */ | ||
| goto fail; |
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.
I'm not clear on why this path doesn't return NotImplemented in py3
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.
The reason is that the comparison is actually implemented, i.e., the error is real and we act just like we would do for __add__ (note that the behaviour was the same before this PR).
The argument parsing for ufuncs contains special logic to enable returning
NotImplementedfor comparison functions. The ufuncs, however, should not have to know whether they were called via a python comparison operator, so this PR moves the logic to the operators, checking after ufunc failedwhether a
NotImplementedshould be returned.Follow-up of #11260, in particular #11260 (comment)