python / python/cpython

Inconsistent handling of the modulo argument for ternary pow() (pure-Python vs extension)

Ouverte
#151,118 2 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

interpreter-core type-bug
Langage dominant
Python
Étoiles
77.2k
Forks
35.9k
Métriques de merge des PR
Métriques de PR en attente

Description

Bug report

Bug description:

This is a follow-up of the https://github.com/python/cpython/issues/130104.

An example with the stdlib:

>>> import decimal, _pydecimal
>>> pow(2, 3, decimal.Decimal(4))
Decimal('0')
>>> pow(2, 3, _pydecimal.Decimal(4))
Traceback (most recent call last):
  File "<python-input-5>", line 1, in <module>
    pow(2, 3, _pydecimal.Decimal(4))
    ~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for ** or pow(): 'int', 'int', 'Decimal'

IIUIC, pow() it just calls the __pow__() for the third argument with original order of ops as a fallback. So, we can just do something like this:

diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 14bc5a4bc4..911c890fcb 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -10377,7 +10377,27 @@ slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus)
         stack[2] = modulus;
         return vectorcall_maybe(tstate, &_Py_ID(__rpow__), stack, 3);
     }
-    Py_RETURN_NOTIMPLEMENTED;
+    stack[0] = self;
+    stack[1] = other;
+    stack[2] = modulus;
+
+    _PyCStackRef cref;
+    _PyThreadState_PushCStackRef(tstate, &cref);
+    int unbound = lookup_maybe_method(modulus, &_Py_ID(__pow__), &cref.ref);
+    PyObject *func = PyStackRef_AsPyObjectBorrow(cref.ref);
+
+    if (func == NULL) {
+        _PyThreadState_PopCStackRef(tstate, &cref);
+        if (!PyErr_Occurred()) {
+            Py_RETURN_NOTIMPLEMENTED;
+        }
+        return NULL;
+    }
+
+    PyObject *retval = vectorcall_unbound(tstate, unbound, func, stack, 3);
+
+    _PyThreadState_PopCStackRef(tstate, &cref);
+    return retval;
 }
 
 SLOT0(slot_nb_negative, __neg__)

Full patch: https://github.com/skirpichev/cpython/pull/9

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez dans Objects/typeobject.c, au niveau de slot_nb_power, et reproduisez les exemples de decimal/_pydecimal du rapport sur un build CPython main. Comparez le comportement de ternary pow() entre les implémentations Pure-Python et d’extension ; le travail est terminé lorsque les deux traitent l’argument modulo de manière cohérente sans réintroduire de régression dans le comportement de fallback existant.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
c, python
Domaine
compilers
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
Calme
Clarté
Plutôt claire
Accessibilité débutants
45/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.