mirror of https://github.com/python/cpython
Issue #26984: int() now always returns an instance of exact int.
This commit is contained in:
parent
d7f3cdd07d
commit
54cd1969ea
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue