gh-130104: Call __rpow__ in ternary pow() if necessary#130251
gh-130104: Call __rpow__ in ternary pow() if necessary#130251serhiy-storchaka merged 5 commits intopython:mainfrom
Conversation
Previously it was only called in binary pow() and the binary power operator.
skirpichev
left a comment
There was a problem hiding this comment.
LGTM (few nitpicks)
Maybe it's possible to refactor code to avoid a copy of SLOT1BINFULL, but I doubt it worth efforts.
| 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.
Maybe you should use object.__rpow__(self, other, modulo=None) signature?
There was a problem hiding this comment.
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.
Sorry, I meant L3329-3342 above.
There was a problem hiding this comment.
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.
picnixz
left a comment
There was a problem hiding this comment.
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.
| * 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.
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.
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.
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.
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.
| 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.
| PyObject* stack[3]; | |
| PyObject *stack[3]; |
| if (r != Py_NotImplemented) | ||
| return r; |
There was a problem hiding this comment.
| 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.
| 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/