summaryrefslogtreecommitdiffstats
path: root/Objects/longobject.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2019-02-25 15:57:58 (GMT)
committerGitHub <noreply@github.com>2019-02-25 15:57:58 (GMT)
commit6a44f6eef3d0958d88882347190b3e2d1222c2e9 (patch)
treebb6474b1e094a672837c3333a081fa4d5d7638f2 /Objects/longobject.c
parentd90a141bb947b68601f8d1f37bc98f7b524f0e01 (diff)
downloadcpython-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/longobject.c')
-rw-r--r--Objects/longobject.c85
1 files changed, 76 insertions, 9 deletions
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;