Issue #26984: int() now always returns an instance of exact int.

This commit is contained in:
Serhiy Storchaka 2016-08-21 20:03:08 +03:00
parent d7f3cdd07d
commit 54cd1969ea
3 changed files with 29 additions and 13 deletions

View File

@ -430,21 +430,24 @@ class IntTestCases(unittest.TestCase):
with self.assertWarns(DeprecationWarning): with self.assertWarns(DeprecationWarning):
n = int(bad_int) n = int(bad_int)
self.assertEqual(n, 1) self.assertEqual(n, 1)
self.assertIs(type(n), int)
bad_int = BadInt2() bad_int = BadInt2()
with self.assertWarns(DeprecationWarning): with self.assertWarns(DeprecationWarning):
n = int(bad_int) n = int(bad_int)
self.assertEqual(n, 1) self.assertEqual(n, 1)
self.assertIs(type(n), int)
bad_int = TruncReturnsBadInt() bad_int = TruncReturnsBadInt()
with self.assertWarns(DeprecationWarning): with self.assertWarns(DeprecationWarning):
n = int(bad_int) n = int(bad_int)
self.assertEqual(n, 1) self.assertEqual(n, 1)
self.assertIs(type(n), int)
good_int = TruncReturnsIntSubclass() good_int = TruncReturnsIntSubclass()
n = int(good_int) n = int(good_int)
self.assertEqual(n, 1) self.assertEqual(n, 1)
self.assertIs(type(n), bool) self.assertIs(type(n), int)
n = IntSubclass(good_int) n = IntSubclass(good_int)
self.assertEqual(n, 1) self.assertEqual(n, 1)
self.assertIs(type(n), IntSubclass) self.assertIs(type(n), IntSubclass)

View File

@ -10,6 +10,8 @@ What's New in Python 3.6.0 beta 1
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #26984: int() now always returns an instance of exact int.
- Issue #25604: Fix a minor bug in integer true division; this bug could - Issue #25604: Fix a minor bug in integer true division; this bug could
potentially have caused off-by-one-ulp results on platforms with potentially have caused off-by-one-ulp results on platforms with
unreliable ldexp implementations. unreliable ldexp implementations.

View File

@ -1281,6 +1281,7 @@ PyNumber_AsSsize_t(PyObject *item, PyObject *err)
PyObject * PyObject *
PyNumber_Long(PyObject *o) PyNumber_Long(PyObject *o)
{ {
PyObject *result;
PyNumberMethods *m; PyNumberMethods *m;
PyObject *trunc_func; PyObject *trunc_func;
Py_buffer view; Py_buffer view;
@ -1296,29 +1297,39 @@ PyNumber_Long(PyObject *o)
} }
m = o->ob_type->tp_as_number; m = o->ob_type->tp_as_number;
if (m && m->nb_int) { /* This should include subclasses of int */ if (m && m->nb_int) { /* This should include subclasses of int */
return (PyObject *)_PyLong_FromNbInt(o); result = (PyObject *)_PyLong_FromNbInt(o);
if (result != NULL && !PyLong_CheckExact(result)) {
Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
}
return result;
} }
trunc_func = _PyObject_LookupSpecial(o, &PyId___trunc__); trunc_func = _PyObject_LookupSpecial(o, &PyId___trunc__);
if (trunc_func) { if (trunc_func) {
PyObject *truncated = PyEval_CallObject(trunc_func, NULL); result = PyEval_CallObject(trunc_func, NULL);
PyObject *int_instance;
Py_DECREF(trunc_func); Py_DECREF(trunc_func);
if (truncated == NULL || PyLong_Check(truncated)) if (result == NULL || PyLong_CheckExact(result)) {
return truncated; return result;
}
if (PyLong_Check(result)) {
Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
return result;
}
/* __trunc__ is specified to return an Integral type, /* __trunc__ is specified to return an Integral type,
but int() needs to return an int. */ but int() needs to return an int. */
m = truncated->ob_type->tp_as_number; m = result->ob_type->tp_as_number;
if (m == NULL || m->nb_int == NULL) { if (m == NULL || m->nb_int == NULL) {
PyErr_Format( PyErr_Format(
PyExc_TypeError, PyExc_TypeError,
"__trunc__ returned non-Integral (type %.200s)", "__trunc__ returned non-Integral (type %.200s)",
truncated->ob_type->tp_name); result->ob_type->tp_name);
Py_DECREF(truncated); Py_DECREF(result);
return NULL; return NULL;
} }
int_instance = (PyObject *)_PyLong_FromNbInt(truncated); Py_SETREF(result, (PyObject *)_PyLong_FromNbInt(result));
Py_DECREF(truncated); if (result != NULL && !PyLong_CheckExact(result)) {
return int_instance; Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
}
return result;
} }
if (PyErr_Occurred()) if (PyErr_Occurred())
return NULL; return NULL;
@ -1340,7 +1351,7 @@ PyNumber_Long(PyObject *o)
PyByteArray_GET_SIZE(o), 10); PyByteArray_GET_SIZE(o), 10);
if (PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) == 0) { if (PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) == 0) {
PyObject *result, *bytes; PyObject *bytes;
/* Copy to NUL-terminated buffer. */ /* Copy to NUL-terminated buffer. */
bytes = PyBytes_FromStringAndSize((const char *)view.buf, view.len); bytes = PyBytes_FromStringAndSize((const char *)view.buf, view.len);