diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2019-02-25 15:57:58 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-25 15:57:58 (GMT) |
commit | 6a44f6eef3d0958d88882347190b3e2d1222c2e9 (patch) | |
tree | bb6474b1e094a672837c3333a081fa4d5d7638f2 /Objects | |
parent | d90a141bb947b68601f8d1f37bc98f7b524f0e01 (diff) | |
download | cpython-6a44f6eef3d0958d88882347190b3e2d1222c2e9.zip cpython-6a44f6eef3d0958d88882347190b3e2d1222c2e9.tar.gz cpython-6a44f6eef3d0958d88882347190b3e2d1222c2e9.tar.bz2 |
bpo-36048: Use __index__() instead of __int__() for implicit conversion if available. (GH-11952)
Deprecate using the __int__() method in implicit conversions of Python
numbers to C integers.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/abstract.c | 11 | ||||
-rw-r--r-- | Objects/longobject.c | 85 |
2 files changed, 82 insertions, 14 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c index 0565ba3..68d06ed 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -759,8 +759,9 @@ int PyNumber_Check(PyObject *o) { return o && o->ob_type->tp_as_number && - (o->ob_type->tp_as_number->nb_int || - o->ob_type->tp_as_number->nb_float); + (o->ob_type->tp_as_number->nb_index || + o->ob_type->tp_as_number->nb_int || + o->ob_type->tp_as_number->nb_float); } /* Binary operators */ @@ -1366,7 +1367,7 @@ PyNumber_Long(PyObject *o) } m = o->ob_type->tp_as_number; if (m && m->nb_int) { /* This should include subclasses of int */ - result = (PyObject *)_PyLong_FromNbInt(o); + result = _PyLong_FromNbInt(o); if (result != NULL && !PyLong_CheckExact(result)) { Py_SETREF(result, _PyLong_Copy((PyLongObject *)result)); } @@ -1386,7 +1387,7 @@ PyNumber_Long(PyObject *o) /* __trunc__ is specified to return an Integral type, but int() needs to return an int. */ m = result->ob_type->tp_as_number; - if (m == NULL || m->nb_int == NULL) { + if (m == NULL || (m->nb_index == NULL && m->nb_int == NULL)) { PyErr_Format( PyExc_TypeError, "__trunc__ returned non-Integral (type %.200s)", @@ -1394,7 +1395,7 @@ PyNumber_Long(PyObject *o) Py_DECREF(result); return NULL; } - Py_SETREF(result, (PyObject *)_PyLong_FromNbInt(result)); + Py_SETREF(result, _PyLong_FromNbIndexOrNbInt(result)); if (result != NULL && !PyLong_CheckExact(result)) { Py_SETREF(result, _PyLong_Copy((PyLongObject *)result)); } diff --git a/Objects/longobject.c b/Objects/longobject.c index d7b01ce..1e3445c 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -140,7 +140,7 @@ long_normalize(PyLongObject *v) nb_int slot is not available or the result of the call to nb_int returns something not of type int. */ -PyLongObject * +PyObject * _PyLong_FromNbInt(PyObject *integral) { PyNumberMethods *nb; @@ -149,7 +149,7 @@ _PyLong_FromNbInt(PyObject *integral) /* Fast path for the case that we already have an int. */ if (PyLong_CheckExact(integral)) { Py_INCREF(integral); - return (PyLongObject *)integral; + return integral; } nb = Py_TYPE(integral)->tp_as_number; @@ -164,7 +164,7 @@ _PyLong_FromNbInt(PyObject *integral) of exact type int. */ result = nb->nb_int(integral); if (!result || PyLong_CheckExact(result)) - return (PyLongObject *)result; + return result; if (!PyLong_Check(result)) { PyErr_Format(PyExc_TypeError, "__int__ returned non-int (type %.200s)", @@ -181,7 +181,74 @@ _PyLong_FromNbInt(PyObject *integral) Py_DECREF(result); return NULL; } - return (PyLongObject *)result; + return result; +} + +/* Convert the given object to a PyLongObject using the nb_index or + nb_int slots, if available (the latter is deprecated). + Raise TypeError if either nb_index and nb_int slots are not + available or the result of the call to nb_index or nb_int + returns something not of type int. + Should be replaced with PyNumber_Index after the end of the + deprecation period. +*/ +PyObject * +_PyLong_FromNbIndexOrNbInt(PyObject *integral) +{ + PyNumberMethods *nb; + PyObject *result; + + /* Fast path for the case that we already have an int. */ + if (PyLong_CheckExact(integral)) { + Py_INCREF(integral); + return integral; + } + + nb = Py_TYPE(integral)->tp_as_number; + if (nb == NULL || (nb->nb_index == NULL && nb->nb_int == NULL)) { + PyErr_Format(PyExc_TypeError, + "an integer is required (got type %.200s)", + Py_TYPE(integral)->tp_name); + return NULL; + } + + if (nb->nb_index) { + /* Convert using the nb_index slot, which should return something + of exact type int. */ + result = nb->nb_index(integral); + if (!result || PyLong_CheckExact(result)) + return result; + if (!PyLong_Check(result)) { + PyErr_Format(PyExc_TypeError, + "__index__ returned non-int (type %.200s)", + result->ob_type->tp_name); + Py_DECREF(result); + return NULL; + } + /* Issue #17576: warn if 'result' not of exact type int. */ + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__index__ returned non-int (type %.200s). " + "The ability to return an instance of a strict subclass of int " + "is deprecated, and may be removed in a future version of Python.", + result->ob_type->tp_name)) + { + Py_DECREF(result); + return NULL; + } + return result; + } + + result = _PyLong_FromNbInt(integral); + if (result && PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "an integer is required (got type %.200s). " + "Implicit conversion to integers using __int__ is deprecated, " + "and may be removed in a future version of Python.", + Py_TYPE(integral)->tp_name)) + { + Py_DECREF(result); + return NULL; + } + return result; } @@ -420,7 +487,7 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow) v = (PyLongObject *)vv; } else { - v = _PyLong_FromNbInt(vv); + v = (PyLongObject *)_PyLong_FromNbIndexOrNbInt(vv); if (v == NULL) return -1; do_decref = 1; @@ -700,7 +767,7 @@ PyLong_AsUnsignedLongMask(PyObject *op) return _PyLong_AsUnsignedLongMask(op); } - lo = _PyLong_FromNbInt(op); + lo = (PyLongObject *)_PyLong_FromNbIndexOrNbInt(op); if (lo == NULL) return (unsigned long)-1; @@ -1229,7 +1296,7 @@ PyLong_AsLongLong(PyObject *vv) v = (PyLongObject *)vv; } else { - v = _PyLong_FromNbInt(vv); + v = (PyLongObject *)_PyLong_FromNbIndexOrNbInt(vv); if (v == NULL) return -1; do_decref = 1; @@ -1344,7 +1411,7 @@ PyLong_AsUnsignedLongLongMask(PyObject *op) return _PyLong_AsUnsignedLongLongMask(op); } - lo = _PyLong_FromNbInt(op); + lo = (PyLongObject *)_PyLong_FromNbIndexOrNbInt(op); if (lo == NULL) return (unsigned long long)-1; @@ -1384,7 +1451,7 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow) v = (PyLongObject *)vv; } else { - v = _PyLong_FromNbInt(vv); + v = (PyLongObject *)_PyLong_FromNbIndexOrNbInt(vv); if (v == NULL) return -1; do_decref = 1; |