mirror of https://github.com/python/cpython
Issue #17576: Deprecation warning emitted now when __int__() or __index__()
return not int instance. Introduced _PyLong_FromNbInt() and refactored PyLong_As*() functions.
This commit is contained in:
parent
acd17304d2
commit
31a655411a
|
@ -152,6 +152,12 @@ PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v,
|
|||
unsigned char* bytes, size_t n,
|
||||
int little_endian, int is_signed);
|
||||
|
||||
/* _PyLong_FromNbInt: Convert the given object to a PyLongObject
|
||||
using the nb_int slot, if available. Raise TypeError if either the
|
||||
nb_int slot is not available or the result of the call to nb_int
|
||||
returns something not of type int.
|
||||
*/
|
||||
PyAPI_FUNC(PyLongObject *)_PyLong_FromNbInt(PyObject *);
|
||||
|
||||
/* _PyLong_Format: Convert the long to a string object with given base,
|
||||
appending a base prefix of 0[box] if base is 2, 8 or 16. */
|
||||
|
|
|
@ -50,12 +50,34 @@ class Int:
|
|||
def __int__(self):
|
||||
return 99
|
||||
|
||||
class IntSubclass(int):
|
||||
def __int__(self):
|
||||
return 99
|
||||
|
||||
class BadInt:
|
||||
def __int__(self):
|
||||
return 1.0
|
||||
|
||||
class BadInt2:
|
||||
def __int__(self):
|
||||
return True
|
||||
|
||||
class BadInt3(int):
|
||||
def __int__(self):
|
||||
return True
|
||||
|
||||
|
||||
class Unsigned_TestCase(unittest.TestCase):
|
||||
def test_b(self):
|
||||
from _testcapi import getargs_b
|
||||
# b returns 'unsigned char', and does range checking (0 ... UCHAR_MAX)
|
||||
self.assertRaises(TypeError, getargs_b, 3.14)
|
||||
self.assertEqual(99, getargs_b(Int()))
|
||||
self.assertEqual(0, getargs_b(IntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_b, BadInt())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(1, getargs_b(BadInt2()))
|
||||
self.assertEqual(0, getargs_b(BadInt3()))
|
||||
|
||||
self.assertRaises(OverflowError, getargs_b, -1)
|
||||
self.assertEqual(0, getargs_b(0))
|
||||
|
@ -70,6 +92,11 @@ class Unsigned_TestCase(unittest.TestCase):
|
|||
# B returns 'unsigned char', no range checking
|
||||
self.assertRaises(TypeError, getargs_B, 3.14)
|
||||
self.assertEqual(99, getargs_B(Int()))
|
||||
self.assertEqual(0, getargs_B(IntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_B, BadInt())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(1, getargs_B(BadInt2()))
|
||||
self.assertEqual(0, getargs_B(BadInt3()))
|
||||
|
||||
self.assertEqual(UCHAR_MAX, getargs_B(-1))
|
||||
self.assertEqual(0, getargs_B(0))
|
||||
|
@ -84,6 +111,11 @@ class Unsigned_TestCase(unittest.TestCase):
|
|||
# H returns 'unsigned short', no range checking
|
||||
self.assertRaises(TypeError, getargs_H, 3.14)
|
||||
self.assertEqual(99, getargs_H(Int()))
|
||||
self.assertEqual(0, getargs_H(IntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_H, BadInt())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(1, getargs_H(BadInt2()))
|
||||
self.assertEqual(0, getargs_H(BadInt3()))
|
||||
|
||||
self.assertEqual(USHRT_MAX, getargs_H(-1))
|
||||
self.assertEqual(0, getargs_H(0))
|
||||
|
@ -99,6 +131,11 @@ class Unsigned_TestCase(unittest.TestCase):
|
|||
# I returns 'unsigned int', no range checking
|
||||
self.assertRaises(TypeError, getargs_I, 3.14)
|
||||
self.assertEqual(99, getargs_I(Int()))
|
||||
self.assertEqual(0, getargs_I(IntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_I, BadInt())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(1, getargs_I(BadInt2()))
|
||||
self.assertEqual(0, getargs_I(BadInt3()))
|
||||
|
||||
self.assertEqual(UINT_MAX, getargs_I(-1))
|
||||
self.assertEqual(0, getargs_I(0))
|
||||
|
@ -115,6 +152,10 @@ class Unsigned_TestCase(unittest.TestCase):
|
|||
# it does not accept float, or instances with __int__
|
||||
self.assertRaises(TypeError, getargs_k, 3.14)
|
||||
self.assertRaises(TypeError, getargs_k, Int())
|
||||
self.assertEqual(0, getargs_k(IntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_k, BadInt())
|
||||
self.assertRaises(TypeError, getargs_k, BadInt2())
|
||||
self.assertEqual(0, getargs_k(BadInt3()))
|
||||
|
||||
self.assertEqual(ULONG_MAX, getargs_k(-1))
|
||||
self.assertEqual(0, getargs_k(0))
|
||||
|
@ -131,6 +172,11 @@ class Signed_TestCase(unittest.TestCase):
|
|||
# h returns 'short', and does range checking (SHRT_MIN ... SHRT_MAX)
|
||||
self.assertRaises(TypeError, getargs_h, 3.14)
|
||||
self.assertEqual(99, getargs_h(Int()))
|
||||
self.assertEqual(0, getargs_h(IntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_h, BadInt())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(1, getargs_h(BadInt2()))
|
||||
self.assertEqual(0, getargs_h(BadInt3()))
|
||||
|
||||
self.assertRaises(OverflowError, getargs_h, SHRT_MIN-1)
|
||||
self.assertEqual(SHRT_MIN, getargs_h(SHRT_MIN))
|
||||
|
@ -145,6 +191,11 @@ class Signed_TestCase(unittest.TestCase):
|
|||
# i returns 'int', and does range checking (INT_MIN ... INT_MAX)
|
||||
self.assertRaises(TypeError, getargs_i, 3.14)
|
||||
self.assertEqual(99, getargs_i(Int()))
|
||||
self.assertEqual(0, getargs_i(IntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_i, BadInt())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(1, getargs_i(BadInt2()))
|
||||
self.assertEqual(0, getargs_i(BadInt3()))
|
||||
|
||||
self.assertRaises(OverflowError, getargs_i, INT_MIN-1)
|
||||
self.assertEqual(INT_MIN, getargs_i(INT_MIN))
|
||||
|
@ -159,6 +210,11 @@ class Signed_TestCase(unittest.TestCase):
|
|||
# l returns 'long', and does range checking (LONG_MIN ... LONG_MAX)
|
||||
self.assertRaises(TypeError, getargs_l, 3.14)
|
||||
self.assertEqual(99, getargs_l(Int()))
|
||||
self.assertEqual(0, getargs_l(IntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_l, BadInt())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(1, getargs_l(BadInt2()))
|
||||
self.assertEqual(0, getargs_l(BadInt3()))
|
||||
|
||||
self.assertRaises(OverflowError, getargs_l, LONG_MIN-1)
|
||||
self.assertEqual(LONG_MIN, getargs_l(LONG_MIN))
|
||||
|
@ -174,6 +230,10 @@ class Signed_TestCase(unittest.TestCase):
|
|||
# (PY_SSIZE_T_MIN ... PY_SSIZE_T_MAX)
|
||||
self.assertRaises(TypeError, getargs_n, 3.14)
|
||||
self.assertRaises(TypeError, getargs_n, Int())
|
||||
self.assertEqual(0, getargs_n(IntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_n, BadInt())
|
||||
self.assertRaises(TypeError, getargs_n, BadInt2())
|
||||
self.assertEqual(0, getargs_n(BadInt3()))
|
||||
|
||||
self.assertRaises(OverflowError, getargs_n, PY_SSIZE_T_MIN-1)
|
||||
self.assertEqual(PY_SSIZE_T_MIN, getargs_n(PY_SSIZE_T_MIN))
|
||||
|
@ -192,6 +252,11 @@ class LongLong_TestCase(unittest.TestCase):
|
|||
self.assertRaises(TypeError, getargs_L, 3.14)
|
||||
self.assertRaises(TypeError, getargs_L, "Hello")
|
||||
self.assertEqual(99, getargs_L(Int()))
|
||||
self.assertEqual(0, getargs_L(IntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_L, BadInt())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(1, getargs_L(BadInt2()))
|
||||
self.assertEqual(0, getargs_L(BadInt3()))
|
||||
|
||||
self.assertRaises(OverflowError, getargs_L, LLONG_MIN-1)
|
||||
self.assertEqual(LLONG_MIN, getargs_L(LLONG_MIN))
|
||||
|
@ -206,6 +271,11 @@ class LongLong_TestCase(unittest.TestCase):
|
|||
# K return 'unsigned long long', no range checking
|
||||
self.assertRaises(TypeError, getargs_K, 3.14)
|
||||
self.assertRaises(TypeError, getargs_K, Int())
|
||||
self.assertEqual(0, getargs_K(IntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_K, BadInt())
|
||||
self.assertRaises(TypeError, getargs_K, BadInt2())
|
||||
self.assertEqual(0, getargs_K(BadInt3()))
|
||||
|
||||
self.assertEqual(ULLONG_MAX, getargs_K(ULLONG_MAX))
|
||||
self.assertEqual(0, getargs_K(0))
|
||||
self.assertEqual(0, getargs_K(ULLONG_MAX+1))
|
||||
|
|
|
@ -9,7 +9,7 @@ class newstyle:
|
|||
|
||||
class TrapInt(int):
|
||||
def __index__(self):
|
||||
return self
|
||||
return int(self)
|
||||
|
||||
class BaseTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
@ -55,6 +55,40 @@ class BaseTestCase(unittest.TestCase):
|
|||
self.assertRaises(TypeError, slice(self.o).indices, 0)
|
||||
self.assertRaises(TypeError, slice(self.n).indices, 0)
|
||||
|
||||
def test_int_subclass_with_index(self):
|
||||
# __index__ should be used when computing indices, even for int
|
||||
# subclasses. See issue #17576.
|
||||
class MyInt(int):
|
||||
def __index__(self):
|
||||
return int(self) + 1
|
||||
|
||||
my_int = MyInt(7)
|
||||
direct_index = my_int.__index__()
|
||||
operator_index = operator.index(my_int)
|
||||
self.assertEqual(direct_index, 8)
|
||||
self.assertEqual(operator_index, 7)
|
||||
# Both results should be of exact type int.
|
||||
self.assertIs(type(direct_index), int)
|
||||
#self.assertIs(type(operator_index), int)
|
||||
|
||||
def test_index_returns_int_subclass(self):
|
||||
class BadInt:
|
||||
def __index__(self):
|
||||
return True
|
||||
|
||||
class BadInt2(int):
|
||||
def __index__(self):
|
||||
return True
|
||||
|
||||
bad_int = BadInt()
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
n = operator.index(bad_int)
|
||||
self.assertEqual(n, 1)
|
||||
|
||||
bad_int = BadInt2()
|
||||
n = operator.index(bad_int)
|
||||
self.assertEqual(n, 0)
|
||||
|
||||
|
||||
class SeqTestCase:
|
||||
# This test case isn't run directly. It just defines common tests
|
||||
|
|
|
@ -263,32 +263,7 @@ class IntTestCases(unittest.TestCase):
|
|||
def __int__(self):
|
||||
return 42
|
||||
|
||||
class Foo1(object):
|
||||
def __int__(self):
|
||||
return 42
|
||||
|
||||
class Foo2(int):
|
||||
def __int__(self):
|
||||
return 42
|
||||
|
||||
class Foo3(int):
|
||||
def __int__(self):
|
||||
return self
|
||||
|
||||
class Foo4(int):
|
||||
def __int__(self):
|
||||
return 42
|
||||
|
||||
class Foo5(int):
|
||||
def __int__(self):
|
||||
return 42.
|
||||
|
||||
self.assertEqual(int(Foo0()), 42)
|
||||
self.assertEqual(int(Foo1()), 42)
|
||||
self.assertEqual(int(Foo2()), 42)
|
||||
self.assertEqual(int(Foo3()), 0)
|
||||
self.assertEqual(int(Foo4()), 42)
|
||||
self.assertRaises(TypeError, int, Foo5())
|
||||
|
||||
class Classic:
|
||||
pass
|
||||
|
@ -351,6 +326,57 @@ class IntTestCases(unittest.TestCase):
|
|||
with self.assertRaises(TypeError):
|
||||
int(TruncReturnsBadInt())
|
||||
|
||||
def test_int_subclass_with_int(self):
|
||||
class MyInt(int):
|
||||
def __int__(self):
|
||||
return 42
|
||||
|
||||
class BadInt(int):
|
||||
def __int__(self):
|
||||
return 42.0
|
||||
|
||||
my_int = MyInt(7)
|
||||
self.assertEqual(my_int, 7)
|
||||
self.assertEqual(int(my_int), 42)
|
||||
|
||||
self.assertRaises(TypeError, int, BadInt())
|
||||
|
||||
def test_int_returns_int_subclass(self):
|
||||
class BadInt:
|
||||
def __int__(self):
|
||||
return True
|
||||
|
||||
class BadInt2(int):
|
||||
def __int__(self):
|
||||
return True
|
||||
|
||||
class TruncReturnsBadInt:
|
||||
def __trunc__(self):
|
||||
return BadInt()
|
||||
|
||||
class TruncReturnsIntSubclass:
|
||||
def __trunc__(self):
|
||||
return True
|
||||
|
||||
bad_int = BadInt()
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
n = int(bad_int)
|
||||
self.assertEqual(n, 1)
|
||||
|
||||
bad_int = BadInt2()
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
n = int(bad_int)
|
||||
self.assertEqual(n, 1)
|
||||
|
||||
bad_int = TruncReturnsBadInt()
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
n = int(bad_int)
|
||||
self.assertEqual(n, 1)
|
||||
|
||||
good_int = TruncReturnsIntSubclass()
|
||||
n = int(good_int)
|
||||
self.assertEqual(n, 1)
|
||||
|
||||
def test_error_message(self):
|
||||
def check(s, base=None):
|
||||
with self.assertRaises(ValueError,
|
||||
|
|
|
@ -10,6 +10,9 @@ What's New in Python 3.3.4 release candidate 1?
|
|||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- Issue #17576: Deprecation warning emitted now when __int__() or __index__()
|
||||
return not int instance.
|
||||
|
||||
- Issue #19932: Fix typo in import.h, missing whitespaces in function prototypes.
|
||||
|
||||
- Issue #19729: In str.format(), fix recursive expansion in format spec.
|
||||
|
|
|
@ -1132,7 +1132,7 @@ PyNumber_Absolute(PyObject *o)
|
|||
return type_error("bad operand type for abs(): '%.200s'", o);
|
||||
}
|
||||
|
||||
/* Return a Python int from the object item
|
||||
/* Return a Python int from the object item.
|
||||
Raise TypeError if the result is not an int
|
||||
or if the object cannot be interpreted as an index.
|
||||
*/
|
||||
|
@ -1146,21 +1146,30 @@ PyNumber_Index(PyObject *item)
|
|||
Py_INCREF(item);
|
||||
return item;
|
||||
}
|
||||
if (PyIndex_Check(item)) {
|
||||
result = item->ob_type->tp_as_number->nb_index(item);
|
||||
if (result && !PyLong_Check(result)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"__index__ returned non-int "
|
||||
"(type %.200s)",
|
||||
result->ob_type->tp_name);
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!PyIndex_Check(item)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"'%.200s' object cannot be interpreted "
|
||||
"as an integer", item->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
result = item->ob_type->tp_as_number->nb_index(item);
|
||||
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;
|
||||
}
|
||||
|
@ -1212,34 +1221,6 @@ PyNumber_AsSsize_t(PyObject *item, PyObject *err)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Returns the Integral instance converted to an int. The instance is expected
|
||||
to be an int or have an __int__ method. Steals integral's
|
||||
reference. error_format will be used to create the TypeError if integral
|
||||
isn't actually an Integral instance. error_format should be a format string
|
||||
that can accept a char* naming integral's type.
|
||||
*/
|
||||
static PyObject *
|
||||
convert_integral_to_int(PyObject *integral, const char *error_format)
|
||||
{
|
||||
PyNumberMethods *nb;
|
||||
if (PyLong_Check(integral))
|
||||
return integral;
|
||||
nb = Py_TYPE(integral)->tp_as_number;
|
||||
if (nb->nb_int) {
|
||||
PyObject *as_int = nb->nb_int(integral);
|
||||
if (!as_int || PyLong_Check(as_int)) {
|
||||
Py_DECREF(integral);
|
||||
return as_int;
|
||||
}
|
||||
Py_DECREF(as_int);
|
||||
}
|
||||
PyErr_Format(PyExc_TypeError, error_format, Py_TYPE(integral)->tp_name);
|
||||
Py_DECREF(integral);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PyObject *
|
||||
PyNumber_Long(PyObject *o)
|
||||
{
|
||||
|
@ -1257,29 +1238,28 @@ PyNumber_Long(PyObject *o)
|
|||
}
|
||||
m = o->ob_type->tp_as_number;
|
||||
if (m && m->nb_int) { /* This should include subclasses of int */
|
||||
PyObject *res = m->nb_int(o);
|
||||
if (res && !PyLong_Check(res)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"__int__ returned non-int (type %.200s)",
|
||||
res->ob_type->tp_name);
|
||||
Py_DECREF(res);
|
||||
return NULL;
|
||||
}
|
||||
return res;
|
||||
return (PyObject *)_PyLong_FromNbInt(o);
|
||||
}
|
||||
if (PyLong_Check(o)) /* An int subclass without nb_int */
|
||||
return _PyLong_Copy((PyLongObject *)o);
|
||||
trunc_func = _PyObject_LookupSpecial(o, &PyId___trunc__);
|
||||
if (trunc_func) {
|
||||
PyObject *truncated = PyEval_CallObject(trunc_func, NULL);
|
||||
PyObject *int_instance;
|
||||
Py_DECREF(trunc_func);
|
||||
if (truncated == NULL)
|
||||
return NULL;
|
||||
if (truncated == NULL || PyLong_Check(truncated))
|
||||
return truncated;
|
||||
/* __trunc__ is specified to return an Integral type,
|
||||
but int() needs to return a int. */
|
||||
int_instance = convert_integral_to_int(truncated,
|
||||
"__trunc__ returned non-Integral (type %.200s)");
|
||||
m = truncated->ob_type->tp_as_number;
|
||||
if (m == NULL || m->nb_int == NULL) {
|
||||
PyErr_Format(
|
||||
PyExc_TypeError,
|
||||
"__trunc__ returned non-Integral (type %.200s)",
|
||||
truncated->ob_type->tp_name);
|
||||
Py_DECREF(truncated);
|
||||
return NULL;
|
||||
}
|
||||
int_instance = (PyObject *)_PyLong_FromNbInt(truncated);
|
||||
Py_DECREF(truncated);
|
||||
return int_instance;
|
||||
}
|
||||
if (PyErr_Occurred())
|
||||
|
|
|
@ -116,6 +116,56 @@ long_normalize(register PyLongObject *v)
|
|||
return v;
|
||||
}
|
||||
|
||||
/* _PyLong_FromNbInt: Convert the given object to a PyLongObject
|
||||
using the nb_int slot, if available. Raise TypeError if either the
|
||||
nb_int slot is not available or the result of the call to nb_int
|
||||
returns something not of type int.
|
||||
*/
|
||||
PyLongObject *
|
||||
_PyLong_FromNbInt(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 (PyLongObject *)integral;
|
||||
}
|
||||
|
||||
nb = Py_TYPE(integral)->tp_as_number;
|
||||
if (nb == NULL || nb->nb_int == NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"an integer is required (got type %.200s)",
|
||||
Py_TYPE(integral)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Convert using the nb_int slot, which should return something
|
||||
of exact type int. */
|
||||
result = nb->nb_int(integral);
|
||||
if (!result || PyLong_CheckExact(result))
|
||||
return (PyLongObject *)result;
|
||||
if (!PyLong_Check(result)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"__int__ 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,
|
||||
"__int__ 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 (PyLongObject *)result;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate a new int object with size digits.
|
||||
Return NULL and set exception if we run out of memory. */
|
||||
|
||||
|
@ -347,28 +397,17 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!PyLong_Check(vv)) {
|
||||
PyNumberMethods *nb;
|
||||
nb = vv->ob_type->tp_as_number;
|
||||
if (nb == NULL || nb->nb_int == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"an integer is required");
|
||||
return -1;
|
||||
}
|
||||
vv = (*nb->nb_int) (vv);
|
||||
if (vv == NULL)
|
||||
if (PyLong_Check(vv)) {
|
||||
v = (PyLongObject *)vv;
|
||||
}
|
||||
else {
|
||||
v = _PyLong_FromNbInt(vv);
|
||||
if (v == NULL)
|
||||
return -1;
|
||||
do_decref = 1;
|
||||
if (!PyLong_Check(vv)) {
|
||||
Py_DECREF(vv);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"nb_int should return int object");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
res = -1;
|
||||
v = (PyLongObject *)vv;
|
||||
i = Py_SIZE(v);
|
||||
|
||||
switch (i) {
|
||||
|
@ -412,7 +451,7 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
|
|||
}
|
||||
exit:
|
||||
if (do_decref) {
|
||||
Py_DECREF(vv);
|
||||
Py_DECREF(v);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -630,36 +669,25 @@ _PyLong_AsUnsignedLongMask(PyObject *vv)
|
|||
unsigned long
|
||||
PyLong_AsUnsignedLongMask(register PyObject *op)
|
||||
{
|
||||
PyNumberMethods *nb;
|
||||
PyLongObject *lo;
|
||||
unsigned long val;
|
||||
|
||||
if (op && PyLong_Check(op))
|
||||
return _PyLong_AsUnsignedLongMask(op);
|
||||
|
||||
if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
|
||||
nb->nb_int == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "an integer is required");
|
||||
if (op == NULL) {
|
||||
PyErr_BadInternalCall();
|
||||
return (unsigned long)-1;
|
||||
}
|
||||
|
||||
lo = (PyLongObject*) (*nb->nb_int) (op);
|
||||
if (PyLong_Check(op)) {
|
||||
return _PyLong_AsUnsignedLongMask(op);
|
||||
}
|
||||
|
||||
lo = _PyLong_FromNbInt(op);
|
||||
if (lo == NULL)
|
||||
return (unsigned long)-1;
|
||||
if (PyLong_Check(lo)) {
|
||||
val = _PyLong_AsUnsignedLongMask((PyObject *)lo);
|
||||
Py_DECREF(lo);
|
||||
if (PyErr_Occurred())
|
||||
return (unsigned long)-1;
|
||||
return val;
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_DECREF(lo);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"nb_int should return int object");
|
||||
return (unsigned long)-1;
|
||||
}
|
||||
|
||||
val = _PyLong_AsUnsignedLongMask((PyObject *)lo);
|
||||
Py_DECREF(lo);
|
||||
return val;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1169,40 +1197,41 @@ PyLong_AsLongLong(PyObject *vv)
|
|||
PY_LONG_LONG bytes;
|
||||
int one = 1;
|
||||
int res;
|
||||
int do_decref = 0; /* if nb_int was called */
|
||||
|
||||
if (vv == NULL) {
|
||||
PyErr_BadInternalCall();
|
||||
return -1;
|
||||
}
|
||||
if (!PyLong_Check(vv)) {
|
||||
PyNumberMethods *nb;
|
||||
PyObject *io;
|
||||
if ((nb = vv->ob_type->tp_as_number) == NULL ||
|
||||
nb->nb_int == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "an integer is required");
|
||||
|
||||
if (PyLong_Check(vv)) {
|
||||
v = (PyLongObject *)vv;
|
||||
}
|
||||
else {
|
||||
v = _PyLong_FromNbInt(vv);
|
||||
if (v == NULL)
|
||||
return -1;
|
||||
}
|
||||
io = (*nb->nb_int) (vv);
|
||||
if (io == NULL)
|
||||
return -1;
|
||||
if (PyLong_Check(io)) {
|
||||
bytes = PyLong_AsLongLong(io);
|
||||
Py_DECREF(io);
|
||||
return bytes;
|
||||
}
|
||||
Py_DECREF(io);
|
||||
PyErr_SetString(PyExc_TypeError, "integer conversion failed");
|
||||
return -1;
|
||||
do_decref = 1;
|
||||
}
|
||||
|
||||
v = (PyLongObject*)vv;
|
||||
res = 0;
|
||||
switch(Py_SIZE(v)) {
|
||||
case -1: return -(sdigit)v->ob_digit[0];
|
||||
case 0: return 0;
|
||||
case 1: return v->ob_digit[0];
|
||||
case -1:
|
||||
bytes = -(sdigit)v->ob_digit[0];
|
||||
break;
|
||||
case 0:
|
||||
bytes = 0;
|
||||
break;
|
||||
case 1:
|
||||
bytes = v->ob_digit[0];
|
||||
break;
|
||||
default:
|
||||
res = _PyLong_AsByteArray((PyLongObject *)v, (unsigned char *)&bytes,
|
||||
SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
|
||||
}
|
||||
if (do_decref) {
|
||||
Py_DECREF(v);
|
||||
}
|
||||
res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes,
|
||||
SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
|
||||
|
||||
/* Plan 9 can't handle PY_LONG_LONG in ? : expressions */
|
||||
if (res < 0)
|
||||
|
@ -1283,36 +1312,25 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv)
|
|||
unsigned PY_LONG_LONG
|
||||
PyLong_AsUnsignedLongLongMask(register PyObject *op)
|
||||
{
|
||||
PyNumberMethods *nb;
|
||||
PyLongObject *lo;
|
||||
unsigned PY_LONG_LONG val;
|
||||
|
||||
if (op && PyLong_Check(op))
|
||||
return _PyLong_AsUnsignedLongLongMask(op);
|
||||
|
||||
if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
|
||||
nb->nb_int == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "an integer is required");
|
||||
return (unsigned PY_LONG_LONG)-1;
|
||||
if (op == NULL) {
|
||||
PyErr_BadInternalCall();
|
||||
return (unsigned long)-1;
|
||||
}
|
||||
|
||||
lo = (PyLongObject*) (*nb->nb_int) (op);
|
||||
if (PyLong_Check(op)) {
|
||||
return _PyLong_AsUnsignedLongLongMask(op);
|
||||
}
|
||||
|
||||
lo = _PyLong_FromNbInt(op);
|
||||
if (lo == NULL)
|
||||
return (unsigned PY_LONG_LONG)-1;
|
||||
if (PyLong_Check(lo)) {
|
||||
val = _PyLong_AsUnsignedLongLongMask((PyObject *)lo);
|
||||
Py_DECREF(lo);
|
||||
if (PyErr_Occurred())
|
||||
return (unsigned PY_LONG_LONG)-1;
|
||||
return val;
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_DECREF(lo);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"nb_int should return int object");
|
||||
return (unsigned PY_LONG_LONG)-1;
|
||||
}
|
||||
|
||||
val = _PyLong_AsUnsignedLongLongMask((PyObject *)lo);
|
||||
Py_DECREF(lo);
|
||||
return val;
|
||||
}
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
|
||||
|
@ -1343,28 +1361,17 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!PyLong_Check(vv)) {
|
||||
PyNumberMethods *nb;
|
||||
nb = vv->ob_type->tp_as_number;
|
||||
if (nb == NULL || nb->nb_int == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"an integer is required");
|
||||
return -1;
|
||||
}
|
||||
vv = (*nb->nb_int) (vv);
|
||||
if (vv == NULL)
|
||||
if (PyLong_Check(vv)) {
|
||||
v = (PyLongObject *)vv;
|
||||
}
|
||||
else {
|
||||
v = _PyLong_FromNbInt(vv);
|
||||
if (v == NULL)
|
||||
return -1;
|
||||
do_decref = 1;
|
||||
if (!PyLong_Check(vv)) {
|
||||
Py_DECREF(vv);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"nb_int should return int object");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
res = -1;
|
||||
v = (PyLongObject *)vv;
|
||||
i = Py_SIZE(v);
|
||||
|
||||
switch (i) {
|
||||
|
@ -1408,7 +1415,7 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
|
|||
}
|
||||
exit:
|
||||
if (do_decref) {
|
||||
Py_DECREF(vv);
|
||||
Py_DECREF(v);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue