-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
gh-130104: Call __rpow__ in ternary pow() if necessary #130251
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
Previously it was only called in binary pow() and the binary power operator.
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.
LGTM (few nitpicks)
Maybe it's possible to refactor code to avoid a copy of SLOT1BINFULL, but I doubt it worth efforts.
@@ -3356,10 +3356,15 @@ left undefined. | |||
is called if ``type(x).__sub__(x, y)`` returns :data:`NotImplemented` or ``type(y)`` | |||
is a subclass of ``type(x)``. [#]_ | |||
|
|||
.. index:: pair: built-in function; pow | |||
Note that :meth:`__rpow__` should be defined to accept an optional third |
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 you should use object.__rpow__(self, other, modulo=None)
signature?
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 do not understand you. Were and how can it be used?
This sentence is a copy of the corresponding sentence for __pow__
.
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.
Sorry, I meant L3329-3342 above.
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 see. There are other similar cases (for example __round__
), so I will left this for other issue. Actually, __pow__()
and __round__()
are never called with None, so it is not necessary that they support None.
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.
First round of style review only. I'll look at the implementation and implications more in detail either later or tomorrow.
* Three-argument :func:`pow` now try calling :meth:`~object.__rpow__` if necessary. | ||
Previously it was only called in two-argument :func:`!pow` and the binary | ||
power operator. | ||
(Contributed by Serhiy Storchaka in :gh:`130104`.) | ||
|
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.
* Three-argument :func:`pow` now try calling :meth:`~object.__rpow__` if necessary. | |
Previously it was only called in two-argument :func:`!pow` and the binary | |
power operator. | |
(Contributed by Serhiy Storchaka in :gh:`130104`.) | |
* Three-argument :func:`pow` now try calling :meth:`~object.__rpow__` if necessary. | |
Previously it was only called in two-argument :func:`!pow` and the binary | |
power operator. | |
(Contributed by Serhiy Storchaka in :gh:`130104`.) | |
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 is the difference?
@@ -9813,13 +9813,46 @@ slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus) | |||
{ | |||
if (modulus == Py_None) |
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.
Let's insert some PEP-7 here if (modulus == Py_None) { ...
int do_other = !Py_IS_TYPE(self, Py_TYPE(other)) && | ||
Py_TYPE(other)->tp_as_number != NULL && | ||
Py_TYPE(other)->tp_as_number->nb_power == slot_nb_power; |
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.
We use a lot of Py_TYPE(other)
, so I think we can have a variable holding it just for readability.
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 code is a copy of SLOT1BINFULL. I do not want to introduce more difference than necessary.
We can make SLOT1BINFULL supporting the third argument, but I am not sure that it is worth.
int do_other = !Py_IS_TYPE(self, Py_TYPE(other)) && | ||
Py_TYPE(other)->tp_as_number != NULL && | ||
Py_TYPE(other)->tp_as_number->nb_power == slot_nb_power; |
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.
int do_other = !Py_IS_TYPE(self, Py_TYPE(other)) && | |
Py_TYPE(other)->tp_as_number != NULL && | |
Py_TYPE(other)->tp_as_number->nb_power == slot_nb_power; | |
int do_other = !Py_IS_TYPE(self, Py_TYPE(other)) | |
&& Py_TYPE(other)->tp_as_number != NULL | |
&& Py_TYPE(other)->tp_as_number->nb_power == slot_nb_power; |
slot_nb_power, so check before calling self.__pow__. */ | ||
|
||
/* The following code is a copy of SLOT1BINFULL, but for three arguments. */ | ||
PyObject* stack[3]; |
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.
PyObject* stack[3]; | |
PyObject *stack[3]; |
if (r != Py_NotImplemented) | ||
return r; |
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 (r != Py_NotImplemented) | |
return r; | |
if (r != Py_NotImplemented) { | |
return r; | |
} |
if (r != Py_NotImplemented || | ||
Py_IS_TYPE(other, Py_TYPE(self))) | ||
return r; |
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 (r != Py_NotImplemented || | |
Py_IS_TYPE(other, Py_TYPE(self))) | |
return r; | |
if (r != Py_NotImplemented || Py_IS_TYPE(other, Py_TYPE(self))) { | |
return r; | |
} |
Sorry I didn't have time. I will leave for 10 days so I won't be able to review it. If you and Serhiy thinks it's good, then go ahead. If the PR is still not merged when I'm back then I'll try to review it. As for whether I find it useful or not, my answer would be "yes". |
Previously it was only called in binary pow() and the binary power operator.
📚 Documentation preview 📚: https://cpython-previews--130251.org.readthedocs.build/