mirror of
https://github.com/python/cpython.git
synced 2025-12-04 08:34:25 +00:00
Patch #1538606, Patch to fix __index__() clipping.
I modified this patch some by fixing style, some error checking, and adding XXX comments. This patch requires review and some changes are to be expected. I'm checking in now to get the greatest possible review and establish a baseline for moving forward. I don't want this to hold up release if possible.
This commit is contained in:
parent
f3e304297e
commit
8a87f5d37e
19 changed files with 321 additions and 236 deletions
|
|
@ -693,12 +693,31 @@ determination.
|
||||||
\samp{float(\var{o})}.\bifuncindex{float}
|
\samp{float(\var{o})}.\bifuncindex{float}
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
\begin{cfuncdesc}{Py_ssize_t}{PyNumber_Index}{PyObject *o}
|
\begin{cfuncdesc}{PyObject*}{PyNumber_Index}{PyObject *o}
|
||||||
Returns the \var{o} converted to a Py_ssize_t integer on success, or
|
Returns the \var{o} converted to a Python int or long on success or \NULL{}
|
||||||
-1 with an exception raised on failure.
|
with a TypeError exception raised on failure.
|
||||||
\versionadded{2.5}
|
\versionadded{2.5}
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
|
\begin{cfuncdesc}{Py_ssize_t}{PyNumber_AsSsize_t}{PyObject *o, PyObject *exc}
|
||||||
|
Returns \var{o} converted to a Py_ssize_t value if \var{o}
|
||||||
|
can be interpreted as an integer. If \var{o} can be converted to a Python
|
||||||
|
int or long but the attempt to convert to a Py_ssize_t value
|
||||||
|
would raise an \exception{OverflowError}, then the \var{exc} argument
|
||||||
|
is the type of exception that will be raised (usually \exception{IndexError}
|
||||||
|
or \exception{OverflowError}). If \var{exc} is \NULL{}, then the exception
|
||||||
|
is cleared and the value is clipped to \var{PY_SSIZE_T_MIN}
|
||||||
|
for a negative integer or \var{PY_SSIZE_T_MAX} for a positive integer.
|
||||||
|
\versionadded{2.5}
|
||||||
|
\end{cfuncdesc}
|
||||||
|
|
||||||
|
\begin{cfuncdesc}{int}{PyIndex_Check}{PyObject *o}
|
||||||
|
Returns True if \var{o} is an index integer (has the nb_index slot of
|
||||||
|
the tp_as_number structure filled in).
|
||||||
|
\versionadded{2.5}
|
||||||
|
\end{cfuncdesc}
|
||||||
|
|
||||||
|
|
||||||
\section{Sequence Protocol \label{sequence}}
|
\section{Sequence Protocol \label{sequence}}
|
||||||
|
|
||||||
\begin{cfuncdesc}{int}{PySequence_Check}{PyObject *o}
|
\begin{cfuncdesc}{int}{PySequence_Check}{PyObject *o}
|
||||||
|
|
|
||||||
|
|
@ -758,13 +758,27 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PyAPI_FUNC(Py_ssize_t) PyNumber_Index(PyObject *);
|
#define PyIndex_Check(obj) \
|
||||||
|
((obj)->ob_type->tp_as_number != NULL && \
|
||||||
|
PyType_HasFeature((obj)->ob_type, Py_TPFLAGS_HAVE_INDEX) && \
|
||||||
|
(obj)->ob_type->tp_as_number->nb_index != NULL)
|
||||||
|
|
||||||
|
PyAPI_FUNC(PyObject *) PyNumber_Index(PyObject *o);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns the object converted to Py_ssize_t on success
|
Returns the object converted to a Python long or int
|
||||||
or -1 with an error raised on failure.
|
or NULL with an error raised on failure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
PyAPI_FUNC(Py_ssize_t) PyNumber_AsSsize_t(PyObject *o, PyObject *exc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns the object converted to Py_ssize_t by going through
|
||||||
|
PyNumber_Index first. If an overflow error occurs while
|
||||||
|
converting the int-or-long to Py_ssize_t, then the second argument
|
||||||
|
is the error-type to return. If it is NULL, then the overflow error
|
||||||
|
is cleared and the value is clipped.
|
||||||
|
*/
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) PyNumber_Int(PyObject *o);
|
PyAPI_FUNC(PyObject *) PyNumber_Int(PyObject *o);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,7 @@ typedef struct {
|
||||||
binaryfunc nb_inplace_true_divide;
|
binaryfunc nb_inplace_true_divide;
|
||||||
|
|
||||||
/* Added in release 2.5 */
|
/* Added in release 2.5 */
|
||||||
lenfunc nb_index;
|
unaryfunc nb_index;
|
||||||
} PyNumberMethods;
|
} PyNumberMethods;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import unittest
|
import unittest
|
||||||
from test import test_support
|
from test import test_support
|
||||||
import operator
|
import operator
|
||||||
|
from sys import maxint
|
||||||
|
|
||||||
class oldstyle:
|
class oldstyle:
|
||||||
def __index__(self):
|
def __index__(self):
|
||||||
|
|
@ -10,68 +11,115 @@ class newstyle(object):
|
||||||
def __index__(self):
|
def __index__(self):
|
||||||
return self.ind
|
return self.ind
|
||||||
|
|
||||||
|
class TrapInt(int):
|
||||||
|
def __index__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
class TrapLong(long):
|
||||||
|
def __index__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
class BaseTestCase(unittest.TestCase):
|
class BaseTestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.o = oldstyle()
|
||||||
|
self.n = newstyle()
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
self.o.ind = -2
|
||||||
|
self.n.ind = 2
|
||||||
|
self.assertEqual(operator.index(self.o), -2)
|
||||||
|
self.assertEqual(operator.index(self.n), 2)
|
||||||
|
|
||||||
|
def test_slice(self):
|
||||||
|
self.o.ind = 1
|
||||||
|
self.n.ind = 2
|
||||||
|
slc = slice(self.o, self.o, self.o)
|
||||||
|
check_slc = slice(1, 1, 1)
|
||||||
|
self.assertEqual(slc.indices(self.o), check_slc.indices(1))
|
||||||
|
slc = slice(self.n, self.n, self.n)
|
||||||
|
check_slc = slice(2, 2, 2)
|
||||||
|
self.assertEqual(slc.indices(self.n), check_slc.indices(2))
|
||||||
|
|
||||||
|
def test_wrappers(self):
|
||||||
|
self.o.ind = 4
|
||||||
|
self.n.ind = 5
|
||||||
|
self.assertEqual(6 .__index__(), 6)
|
||||||
|
self.assertEqual(-7L.__index__(), -7)
|
||||||
|
self.assertEqual(self.o.__index__(), 4)
|
||||||
|
self.assertEqual(self.n.__index__(), 5)
|
||||||
|
|
||||||
|
def test_infinite_recursion(self):
|
||||||
|
self.failUnlessRaises(TypeError, operator.index, TrapInt())
|
||||||
|
self.failUnlessRaises(TypeError, operator.index, TrapLong())
|
||||||
|
self.failUnless(slice(TrapInt()).indices(0)==(0,0,1))
|
||||||
|
self.failUnlessRaises(TypeError, slice(TrapLong()).indices, 0)
|
||||||
|
|
||||||
|
def test_error(self):
|
||||||
|
self.o.ind = 'dumb'
|
||||||
|
self.n.ind = 'bad'
|
||||||
|
self.failUnlessRaises(TypeError, operator.index, self.o)
|
||||||
|
self.failUnlessRaises(TypeError, operator.index, self.n)
|
||||||
|
self.failUnlessRaises(TypeError, slice(self.o).indices, 0)
|
||||||
|
self.failUnlessRaises(TypeError, slice(self.n).indices, 0)
|
||||||
|
|
||||||
|
|
||||||
|
class SeqTestCase(unittest.TestCase):
|
||||||
|
# This test case isn't run directly. It just defines common tests
|
||||||
|
# to the different sequence types below
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.o = oldstyle()
|
self.o = oldstyle()
|
||||||
self.n = newstyle()
|
self.n = newstyle()
|
||||||
self.o2 = oldstyle()
|
self.o2 = oldstyle()
|
||||||
self.n2 = newstyle()
|
self.n2 = newstyle()
|
||||||
|
|
||||||
def test_basic(self):
|
def test_index(self):
|
||||||
self.o.ind = -2
|
self.o.ind = -2
|
||||||
self.n.ind = 2
|
self.n.ind = 2
|
||||||
assert(self.seq[self.n] == self.seq[2])
|
self.assertEqual(self.seq[self.n], self.seq[2])
|
||||||
assert(self.seq[self.o] == self.seq[-2])
|
self.assertEqual(self.seq[self.o], self.seq[-2])
|
||||||
assert(operator.index(self.o) == -2)
|
|
||||||
assert(operator.index(self.n) == 2)
|
|
||||||
|
|
||||||
def test_error(self):
|
|
||||||
self.o.ind = 'dumb'
|
|
||||||
self.n.ind = 'bad'
|
|
||||||
myfunc = lambda x, obj: obj.seq[x]
|
|
||||||
self.failUnlessRaises(TypeError, operator.index, self.o)
|
|
||||||
self.failUnlessRaises(TypeError, operator.index, self.n)
|
|
||||||
self.failUnlessRaises(TypeError, myfunc, self.o, self)
|
|
||||||
self.failUnlessRaises(TypeError, myfunc, self.n, self)
|
|
||||||
|
|
||||||
def test_slice(self):
|
def test_slice(self):
|
||||||
self.o.ind = 1
|
self.o.ind = 1
|
||||||
self.o2.ind = 3
|
self.o2.ind = 3
|
||||||
self.n.ind = 2
|
self.n.ind = 2
|
||||||
self.n2.ind = 4
|
self.n2.ind = 4
|
||||||
assert(self.seq[self.o:self.o2] == self.seq[1:3])
|
self.assertEqual(self.seq[self.o:self.o2], self.seq[1:3])
|
||||||
assert(self.seq[self.n:self.n2] == self.seq[2:4])
|
self.assertEqual(self.seq[self.n:self.n2], self.seq[2:4])
|
||||||
|
|
||||||
def test_repeat(self):
|
def test_repeat(self):
|
||||||
self.o.ind = 3
|
self.o.ind = 3
|
||||||
self.n.ind = 2
|
self.n.ind = 2
|
||||||
assert(self.seq * self.o == self.seq * 3)
|
self.assertEqual(self.seq * self.o, self.seq * 3)
|
||||||
assert(self.seq * self.n == self.seq * 2)
|
self.assertEqual(self.seq * self.n, self.seq * 2)
|
||||||
assert(self.o * self.seq == self.seq * 3)
|
self.assertEqual(self.o * self.seq, self.seq * 3)
|
||||||
assert(self.n * self.seq == self.seq * 2)
|
self.assertEqual(self.n * self.seq, self.seq * 2)
|
||||||
|
|
||||||
def test_wrappers(self):
|
def test_wrappers(self):
|
||||||
n = self.n
|
self.o.ind = 4
|
||||||
n.ind = 5
|
self.n.ind = 5
|
||||||
assert n.__index__() == 5
|
self.assertEqual(self.seq.__getitem__(self.o), self.seq[4])
|
||||||
assert 6 .__index__() == 6
|
self.assertEqual(self.seq.__mul__(self.o), self.seq * 4)
|
||||||
assert -7L.__index__() == -7
|
self.assertEqual(self.seq.__rmul__(self.o), self.seq * 4)
|
||||||
assert self.seq.__getitem__(n) == self.seq[5]
|
self.assertEqual(self.seq.__getitem__(self.n), self.seq[5])
|
||||||
assert self.seq.__mul__(n) == self.seq * 5
|
self.assertEqual(self.seq.__mul__(self.n), self.seq * 5)
|
||||||
assert self.seq.__rmul__(n) == self.seq * 5
|
self.assertEqual(self.seq.__rmul__(self.n), self.seq * 5)
|
||||||
|
|
||||||
def test_infinite_recusion(self):
|
def test_infinite_recursion(self):
|
||||||
class Trap1(int):
|
self.failUnlessRaises(TypeError, operator.getitem, self.seq, TrapInt())
|
||||||
def __index__(self):
|
self.failUnlessRaises(TypeError, operator.getitem, self.seq, TrapLong())
|
||||||
return self
|
|
||||||
class Trap2(long):
|
def test_error(self):
|
||||||
def __index__(self):
|
self.o.ind = 'dumb'
|
||||||
return self
|
self.n.ind = 'bad'
|
||||||
self.failUnlessRaises(TypeError, operator.getitem, self.seq, Trap1())
|
indexobj = lambda x, obj: obj.seq[x]
|
||||||
self.failUnlessRaises(TypeError, operator.getitem, self.seq, Trap2())
|
self.failUnlessRaises(TypeError, indexobj, self.o, self)
|
||||||
|
self.failUnlessRaises(TypeError, indexobj, self.n, self)
|
||||||
|
sliceobj = lambda x, obj: obj.seq[x:]
|
||||||
|
self.failUnlessRaises(TypeError, sliceobj, self.o, self)
|
||||||
|
self.failUnlessRaises(TypeError, sliceobj, self.n, self)
|
||||||
|
|
||||||
|
|
||||||
class ListTestCase(BaseTestCase):
|
class ListTestCase(SeqTestCase):
|
||||||
seq = [0,10,20,30,40,50]
|
seq = [0,10,20,30,40,50]
|
||||||
|
|
||||||
def test_setdelitem(self):
|
def test_setdelitem(self):
|
||||||
|
|
@ -82,36 +130,36 @@ class ListTestCase(BaseTestCase):
|
||||||
del lst[self.n]
|
del lst[self.n]
|
||||||
lst[self.o] = 'X'
|
lst[self.o] = 'X'
|
||||||
lst[self.n] = 'Y'
|
lst[self.n] = 'Y'
|
||||||
assert lst == list('abYdefghXj')
|
self.assertEqual(lst, list('abYdefghXj'))
|
||||||
|
|
||||||
lst = [5, 6, 7, 8, 9, 10, 11]
|
lst = [5, 6, 7, 8, 9, 10, 11]
|
||||||
lst.__setitem__(self.n, "here")
|
lst.__setitem__(self.n, "here")
|
||||||
assert lst == [5, 6, "here", 8, 9, 10, 11]
|
self.assertEqual(lst, [5, 6, "here", 8, 9, 10, 11])
|
||||||
lst.__delitem__(self.n)
|
lst.__delitem__(self.n)
|
||||||
assert lst == [5, 6, 8, 9, 10, 11]
|
self.assertEqual(lst, [5, 6, 8, 9, 10, 11])
|
||||||
|
|
||||||
def test_inplace_repeat(self):
|
def test_inplace_repeat(self):
|
||||||
self.o.ind = 2
|
self.o.ind = 2
|
||||||
self.n.ind = 3
|
self.n.ind = 3
|
||||||
lst = [6, 4]
|
lst = [6, 4]
|
||||||
lst *= self.o
|
lst *= self.o
|
||||||
assert lst == [6, 4, 6, 4]
|
self.assertEqual(lst, [6, 4, 6, 4])
|
||||||
lst *= self.n
|
lst *= self.n
|
||||||
assert lst == [6, 4, 6, 4] * 3
|
self.assertEqual(lst, [6, 4, 6, 4] * 3)
|
||||||
|
|
||||||
lst = [5, 6, 7, 8, 9, 11]
|
lst = [5, 6, 7, 8, 9, 11]
|
||||||
l2 = lst.__imul__(self.n)
|
l2 = lst.__imul__(self.n)
|
||||||
assert l2 is lst
|
self.assert_(l2 is lst)
|
||||||
assert lst == [5, 6, 7, 8, 9, 11] * 3
|
self.assertEqual(lst, [5, 6, 7, 8, 9, 11] * 3)
|
||||||
|
|
||||||
|
|
||||||
class TupleTestCase(BaseTestCase):
|
class TupleTestCase(SeqTestCase):
|
||||||
seq = (0,10,20,30,40,50)
|
seq = (0,10,20,30,40,50)
|
||||||
|
|
||||||
class StringTestCase(BaseTestCase):
|
class StringTestCase(SeqTestCase):
|
||||||
seq = "this is a test"
|
seq = "this is a test"
|
||||||
|
|
||||||
class UnicodeTestCase(BaseTestCase):
|
class UnicodeTestCase(SeqTestCase):
|
||||||
seq = u"this is a test"
|
seq = u"this is a test"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -120,17 +168,47 @@ class XRangeTestCase(unittest.TestCase):
|
||||||
def test_xrange(self):
|
def test_xrange(self):
|
||||||
n = newstyle()
|
n = newstyle()
|
||||||
n.ind = 5
|
n.ind = 5
|
||||||
assert xrange(1, 20)[n] == 6
|
self.assertEqual(xrange(1, 20)[n], 6)
|
||||||
assert xrange(1, 20).__getitem__(n) == 6
|
self.assertEqual(xrange(1, 20).__getitem__(n), 6)
|
||||||
|
|
||||||
|
class OverflowTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.pos = 2**100
|
||||||
|
self.neg = -self.pos
|
||||||
|
|
||||||
|
def test_large_longs(self):
|
||||||
|
self.assertEqual(self.pos.__index__(), self.pos)
|
||||||
|
self.assertEqual(self.neg.__index__(), self.neg)
|
||||||
|
|
||||||
|
def test_getitem(self):
|
||||||
|
class GetItem(object):
|
||||||
|
def __len__(self):
|
||||||
|
return maxint
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return key
|
||||||
|
def __getslice__(self, i, j):
|
||||||
|
return i, j
|
||||||
|
x = GetItem()
|
||||||
|
self.assertEqual(x[self.pos], self.pos)
|
||||||
|
self.assertEqual(x[self.neg], self.neg)
|
||||||
|
self.assertEqual(x[self.neg:self.pos], (-1, maxint))
|
||||||
|
self.assertEqual(x[self.neg:self.pos:1].indices(maxint), (0, maxint, 1))
|
||||||
|
|
||||||
|
def test_sequence_repeat(self):
|
||||||
|
self.failUnlessRaises(OverflowError, lambda: "a" * self.pos)
|
||||||
|
self.failUnlessRaises(OverflowError, lambda: "a" * self.neg)
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
test_support.run_unittest(
|
test_support.run_unittest(
|
||||||
|
BaseTestCase,
|
||||||
ListTestCase,
|
ListTestCase,
|
||||||
TupleTestCase,
|
TupleTestCase,
|
||||||
StringTestCase,
|
StringTestCase,
|
||||||
UnicodeTestCase,
|
UnicodeTestCase,
|
||||||
XRangeTestCase,
|
XRangeTestCase,
|
||||||
|
OverflowTestCase,
|
||||||
)
|
)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@ What's New in Python 2.5 release candidate 1?
|
||||||
Core and builtins
|
Core and builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Patch #1538606, Fix __index__() clipping. There were some problems
|
||||||
|
discovered with the API and how integers that didn't fit into Py_ssize_t
|
||||||
|
were handled. This patch attempts to provide enough alternatives
|
||||||
|
to effectively use __index__.
|
||||||
|
|
||||||
- Bug #1536021: __hash__ may now return long int; the final hash
|
- Bug #1536021: __hash__ may now return long int; the final hash
|
||||||
value is obtained by invoking hash on the long int.
|
value is obtained by invoking hash on the long int.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1572,14 +1572,11 @@ array_repr(arrayobject *a)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
array_subscr(arrayobject* self, PyObject* item)
|
array_subscr(arrayobject* self, PyObject* item)
|
||||||
{
|
{
|
||||||
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
if (PyIndex_Check(item)) {
|
||||||
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||||
Py_ssize_t i = nb->nb_index(item);
|
|
||||||
if (i==-1 && PyErr_Occurred()) {
|
if (i==-1 && PyErr_Occurred()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -1627,9 +1624,8 @@ array_subscr(arrayobject* self, PyObject* item)
|
||||||
static int
|
static int
|
||||||
array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
|
array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
|
||||||
{
|
{
|
||||||
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
if (PyIndex_Check(item)) {
|
||||||
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||||
Py_ssize_t i = nb->nb_index(item);
|
|
||||||
if (i==-1 && PyErr_Occurred())
|
if (i==-1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
|
|
|
||||||
|
|
@ -808,8 +808,6 @@ static PyTypeObject mmap_object_type = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
|
||||||
|
|
||||||
/* extract the map size from the given PyObject
|
/* extract the map size from the given PyObject
|
||||||
|
|
||||||
Returns -1 on error, with an appropriate Python exception raised. On
|
Returns -1 on error, with an appropriate Python exception raised. On
|
||||||
|
|
@ -817,31 +815,19 @@ static PyTypeObject mmap_object_type = {
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
_GetMapSize(PyObject *o)
|
_GetMapSize(PyObject *o)
|
||||||
{
|
{
|
||||||
PyNumberMethods *nb = o->ob_type->tp_as_number;
|
if (PyIndex_Check(o)) {
|
||||||
if (nb != NULL && HASINDEX(o) && nb->nb_index != NULL) {
|
Py_ssize_t i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
|
||||||
Py_ssize_t i = nb->nb_index(o);
|
|
||||||
if (i==-1 && PyErr_Occurred())
|
if (i==-1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
if (i < 0)
|
if (i < 0) {
|
||||||
goto onnegoverflow;
|
|
||||||
if (i==PY_SSIZE_T_MAX)
|
|
||||||
goto onposoverflow;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyErr_SetString(PyExc_TypeError,
|
|
||||||
"map size must be an integral value");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
onnegoverflow:
|
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"memory mapped size must be positive");
|
"memory mapped size must be positive");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
onposoverflow:
|
PyErr_SetString(PyExc_TypeError, "map size must be an integral value");
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
|
||||||
"memory mapped size is too large (limited by C int)");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,15 +139,7 @@ op_ipow(PyObject *s, PyObject *a)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
op_index(PyObject *s, PyObject *a)
|
op_index(PyObject *s, PyObject *a)
|
||||||
{
|
{
|
||||||
Py_ssize_t i;
|
return PyNumber_Index(a);
|
||||||
PyObject *a1;
|
|
||||||
if (!PyArg_UnpackTuple(a,"index", 1, 1, &a1))
|
|
||||||
return NULL;
|
|
||||||
i = PyNumber_Index(a1);
|
|
||||||
if (i == -1 && PyErr_Occurred())
|
|
||||||
return NULL;
|
|
||||||
else
|
|
||||||
return PyInt_FromSsize_t(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
|
|
@ -249,7 +241,7 @@ spam1o(isMappingType,
|
||||||
|
|
||||||
spam1(is_, "is_(a, b) -- Same as a is b.")
|
spam1(is_, "is_(a, b) -- Same as a is b.")
|
||||||
spam1(is_not, "is_not(a, b) -- Same as a is not b.")
|
spam1(is_not, "is_not(a, b) -- Same as a is not b.")
|
||||||
spam2(index, __index__, "index(a) -- Same as a.__index__()")
|
spam2o(index, __index__, "index(a) -- Same as a.__index__()")
|
||||||
spam2(add,__add__, "add(a, b) -- Same as a + b.")
|
spam2(add,__add__, "add(a, b) -- Same as a + b.")
|
||||||
spam2(sub,__sub__, "sub(a, b) -- Same as a - b.")
|
spam2(sub,__sub__, "sub(a, b) -- Same as a - b.")
|
||||||
spam2(mul,__mul__, "mul(a, b) -- Same as a * b.")
|
spam2(mul,__mul__, "mul(a, b) -- Same as a * b.")
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@
|
||||||
#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
|
#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
|
||||||
Py_TPFLAGS_CHECKTYPES)
|
Py_TPFLAGS_CHECKTYPES)
|
||||||
|
|
||||||
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
|
||||||
|
|
||||||
|
|
||||||
/* Shorthands to return certain errors */
|
/* Shorthands to return certain errors */
|
||||||
|
|
||||||
|
|
@ -122,9 +120,9 @@ PyObject_GetItem(PyObject *o, PyObject *key)
|
||||||
return m->mp_subscript(o, key);
|
return m->mp_subscript(o, key);
|
||||||
|
|
||||||
if (o->ob_type->tp_as_sequence) {
|
if (o->ob_type->tp_as_sequence) {
|
||||||
PyNumberMethods *nb = key->ob_type->tp_as_number;
|
if (PyIndex_Check(key)) {
|
||||||
if (nb != NULL && HASINDEX(key) && nb->nb_index != NULL) {
|
Py_ssize_t key_value;
|
||||||
Py_ssize_t key_value = nb->nb_index(key);
|
key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
|
||||||
if (key_value == -1 && PyErr_Occurred())
|
if (key_value == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
return PySequence_GetItem(o, key_value);
|
return PySequence_GetItem(o, key_value);
|
||||||
|
|
@ -151,9 +149,9 @@ PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value)
|
||||||
return m->mp_ass_subscript(o, key, value);
|
return m->mp_ass_subscript(o, key, value);
|
||||||
|
|
||||||
if (o->ob_type->tp_as_sequence) {
|
if (o->ob_type->tp_as_sequence) {
|
||||||
PyNumberMethods *nb = key->ob_type->tp_as_number;
|
if (PyIndex_Check(key)) {
|
||||||
if (nb != NULL && HASINDEX(key) && nb->nb_index != NULL) {
|
Py_ssize_t key_value;
|
||||||
Py_ssize_t key_value = nb->nb_index(key);
|
key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
|
||||||
if (key_value == -1 && PyErr_Occurred())
|
if (key_value == -1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
return PySequence_SetItem(o, key_value, value);
|
return PySequence_SetItem(o, key_value, value);
|
||||||
|
|
@ -183,9 +181,9 @@ PyObject_DelItem(PyObject *o, PyObject *key)
|
||||||
return m->mp_ass_subscript(o, key, (PyObject*)NULL);
|
return m->mp_ass_subscript(o, key, (PyObject*)NULL);
|
||||||
|
|
||||||
if (o->ob_type->tp_as_sequence) {
|
if (o->ob_type->tp_as_sequence) {
|
||||||
PyNumberMethods *nb = key->ob_type->tp_as_number;
|
if (PyIndex_Check(key)) {
|
||||||
if (nb != NULL && HASINDEX(key) && nb->nb_index != NULL) {
|
Py_ssize_t key_value;
|
||||||
Py_ssize_t key_value = nb->nb_index(key);
|
key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
|
||||||
if (key_value == -1 && PyErr_Occurred())
|
if (key_value == -1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
return PySequence_DelItem(o, key_value);
|
return PySequence_DelItem(o, key_value);
|
||||||
|
|
@ -653,9 +651,8 @@ static PyObject *
|
||||||
sequence_repeat(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n)
|
sequence_repeat(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n)
|
||||||
{
|
{
|
||||||
Py_ssize_t count;
|
Py_ssize_t count;
|
||||||
PyNumberMethods *nb = n->ob_type->tp_as_number;
|
if (PyIndex_Check(n)) {
|
||||||
if (nb != NULL && HASINDEX(n) && nb->nb_index != NULL) {
|
count = PyNumber_AsSsize_t(n, PyExc_OverflowError);
|
||||||
count = nb->nb_index(n);
|
|
||||||
if (count == -1 && PyErr_Occurred())
|
if (count == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -938,23 +935,89 @@ int_from_string(const char *s, Py_ssize_t len)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a Py_ssize_t integer from the object item */
|
/* Return a Python Int or Long from the object item
|
||||||
Py_ssize_t
|
Raise TypeError if the result is not an int-or-long
|
||||||
|
or if the object cannot be interpreted as an index.
|
||||||
|
*/
|
||||||
|
PyObject *
|
||||||
PyNumber_Index(PyObject *item)
|
PyNumber_Index(PyObject *item)
|
||||||
{
|
{
|
||||||
Py_ssize_t value = -1;
|
PyObject *result = NULL;
|
||||||
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
if (item == NULL)
|
||||||
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
return null_error();
|
||||||
value = nb->nb_index(item);
|
/* XXX(nnorwitz): should these be CheckExact? Aren't subclasses ok? */
|
||||||
|
if (PyInt_CheckExact(item) || PyLong_CheckExact(item)) {
|
||||||
|
Py_INCREF(item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
if (PyIndex_Check(item)) {
|
||||||
|
result = item->ob_type->tp_as_number->nb_index(item);
|
||||||
|
/* XXX(nnorwitz): Aren't subclasses ok here too? */
|
||||||
|
if (result &&
|
||||||
|
!PyInt_CheckExact(result) && !PyLong_CheckExact(result)) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"__index__ returned non-(int,long) " \
|
||||||
|
"(type %.200s)",
|
||||||
|
result->ob_type->tp_name);
|
||||||
|
Py_DECREF(result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"'%.200s' object cannot be interpreted "
|
"'%.200s' object cannot be interpreted "
|
||||||
"as an index", item->ob_type->tp_name);
|
"as an index", item->ob_type->tp_name);
|
||||||
}
|
}
|
||||||
return value;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return an error on Overflow only if err is not NULL*/
|
||||||
|
|
||||||
|
Py_ssize_t
|
||||||
|
PyNumber_AsSsize_t(PyObject *item, PyObject *err)
|
||||||
|
{
|
||||||
|
Py_ssize_t result;
|
||||||
|
PyObject *runerr;
|
||||||
|
PyObject *value = PyNumber_Index(item);
|
||||||
|
if (value == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* We're done if PyInt_AsSsize_t() returns without error. */
|
||||||
|
result = PyInt_AsSsize_t(value);
|
||||||
|
if (result != -1 || !(runerr = PyErr_Occurred()))
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
/* Error handling code -- only manage OverflowError differently */
|
||||||
|
if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError))
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
PyErr_Clear();
|
||||||
|
/* If no error-handling desired then the default clipping
|
||||||
|
is sufficient.
|
||||||
|
*/
|
||||||
|
if (!err) {
|
||||||
|
assert(PyLong_Check(value));
|
||||||
|
/* Whether or not it is less than or equal to
|
||||||
|
zero is determined by the sign of ob_size
|
||||||
|
*/
|
||||||
|
if (_PyLong_Sign(value) < 0)
|
||||||
|
result = PY_SSIZE_T_MIN;
|
||||||
|
else
|
||||||
|
result = PY_SSIZE_T_MAX;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Otherwise replace the error with caller's error object. */
|
||||||
|
PyErr_Format(err,
|
||||||
|
"cannot fit '%.200s' into an index-sized integer",
|
||||||
|
item->ob_type->tp_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish:
|
||||||
|
Py_DECREF(value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyNumber_Int(PyObject *o)
|
PyNumber_Int(PyObject *o)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1670,40 +1670,28 @@ instance_nonzero(PyInstanceObject *self)
|
||||||
return outcome > 0;
|
return outcome > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Py_ssize_t
|
static PyObject *
|
||||||
instance_index(PyInstanceObject *self)
|
instance_index(PyInstanceObject *self)
|
||||||
{
|
{
|
||||||
PyObject *func, *res;
|
PyObject *func, *res;
|
||||||
Py_ssize_t outcome;
|
|
||||||
static PyObject *indexstr = NULL;
|
static PyObject *indexstr = NULL;
|
||||||
|
|
||||||
if (indexstr == NULL) {
|
if (indexstr == NULL) {
|
||||||
indexstr = PyString_InternFromString("__index__");
|
indexstr = PyString_InternFromString("__index__");
|
||||||
if (indexstr == NULL)
|
if (indexstr == NULL)
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
if ((func = instance_getattr(self, indexstr)) == NULL) {
|
if ((func = instance_getattr(self, indexstr)) == NULL) {
|
||||||
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
|
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
|
||||||
return -1;
|
return NULL;
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"object cannot be interpreted as an index");
|
"object cannot be interpreted as an index");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
res = PyEval_CallObject(func, (PyObject *)NULL);
|
res = PyEval_CallObject(func, (PyObject *)NULL);
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
if (res == NULL)
|
return res;
|
||||||
return -1;
|
|
||||||
if (PyInt_Check(res) || PyLong_Check(res)) {
|
|
||||||
outcome = res->ob_type->tp_as_number->nb_index(res);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyErr_SetString(PyExc_TypeError,
|
|
||||||
"__index__ must return an int or a long");
|
|
||||||
outcome = -1;
|
|
||||||
}
|
|
||||||
Py_DECREF(res);
|
|
||||||
return outcome;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2026,7 +2014,7 @@ static PyNumberMethods instance_as_number = {
|
||||||
instance_truediv, /* nb_true_divide */
|
instance_truediv, /* nb_true_divide */
|
||||||
instance_ifloordiv, /* nb_inplace_floor_divide */
|
instance_ifloordiv, /* nb_inplace_floor_divide */
|
||||||
instance_itruediv, /* nb_inplace_true_divide */
|
instance_itruediv, /* nb_inplace_true_divide */
|
||||||
(lenfunc)instance_index, /* nb_index */
|
(unaryfunc)instance_index, /* nb_index */
|
||||||
};
|
};
|
||||||
|
|
||||||
PyTypeObject PyInstance_Type = {
|
PyTypeObject PyInstance_Type = {
|
||||||
|
|
|
||||||
|
|
@ -193,16 +193,21 @@ PyInt_AsSsize_t(register PyObject *op)
|
||||||
PyIntObject *io;
|
PyIntObject *io;
|
||||||
Py_ssize_t val;
|
Py_ssize_t val;
|
||||||
#endif
|
#endif
|
||||||
if (op && !PyInt_CheckExact(op) && PyLong_Check(op))
|
|
||||||
|
if (op == NULL) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "an integer is required");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyInt_Check(op))
|
||||||
|
return PyInt_AS_LONG((PyIntObject*) op);
|
||||||
|
if (PyLong_Check(op))
|
||||||
return _PyLong_AsSsize_t(op);
|
return _PyLong_AsSsize_t(op);
|
||||||
#if SIZEOF_SIZE_T == SIZEOF_LONG
|
#if SIZEOF_SIZE_T == SIZEOF_LONG
|
||||||
return PyInt_AsLong(op);
|
return PyInt_AsLong(op);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if (op && PyInt_Check(op))
|
if ((nb = op->ob_type->tp_as_number) == NULL ||
|
||||||
return PyInt_AS_LONG((PyIntObject*) op);
|
|
||||||
|
|
||||||
if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
|
|
||||||
(nb->nb_int == NULL && nb->nb_long == 0)) {
|
(nb->nb_int == NULL && nb->nb_long == 0)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "an integer is required");
|
PyErr_SetString(PyExc_TypeError, "an integer is required");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -1079,7 +1084,7 @@ static PyNumberMethods int_as_number = {
|
||||||
int_true_divide, /* nb_true_divide */
|
int_true_divide, /* nb_true_divide */
|
||||||
0, /* nb_inplace_floor_divide */
|
0, /* nb_inplace_floor_divide */
|
||||||
0, /* nb_inplace_true_divide */
|
0, /* nb_inplace_true_divide */
|
||||||
PyInt_AsSsize_t, /* nb_index */
|
(unaryfunc)int_int, /* nb_index */
|
||||||
};
|
};
|
||||||
|
|
||||||
PyTypeObject PyInt_Type = {
|
PyTypeObject PyInt_Type = {
|
||||||
|
|
|
||||||
|
|
@ -2450,14 +2450,13 @@ PyDoc_STRVAR(list_doc,
|
||||||
"list() -> new list\n"
|
"list() -> new list\n"
|
||||||
"list(sequence) -> new list initialized from sequence's items");
|
"list(sequence) -> new list initialized from sequence's items");
|
||||||
|
|
||||||
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
list_subscript(PyListObject* self, PyObject* item)
|
list_subscript(PyListObject* self, PyObject* item)
|
||||||
{
|
{
|
||||||
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
if (PyIndex_Check(item)) {
|
||||||
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
Py_ssize_t i;
|
||||||
Py_ssize_t i = nb->nb_index(item);
|
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
|
|
@ -2504,9 +2503,8 @@ list_subscript(PyListObject* self, PyObject* item)
|
||||||
static int
|
static int
|
||||||
list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
||||||
{
|
{
|
||||||
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
if (PyIndex_Check(item)) {
|
||||||
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||||
Py_ssize_t i = nb->nb_index(item);
|
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
|
|
|
||||||
|
|
@ -240,8 +240,11 @@ PyLong_AsLong(PyObject *vv)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Py_ssize_t
|
/* Get a Py_ssize_t from a long int object.
|
||||||
_long_as_ssize_t(PyObject *vv) {
|
Returns -1 and sets an error condition if overflow occurs. */
|
||||||
|
|
||||||
|
Py_ssize_t
|
||||||
|
_PyLong_AsSsize_t(PyObject *vv) {
|
||||||
register PyLongObject *v;
|
register PyLongObject *v;
|
||||||
size_t x, prev;
|
size_t x, prev;
|
||||||
Py_ssize_t i;
|
Py_ssize_t i;
|
||||||
|
|
@ -277,45 +280,7 @@ _long_as_ssize_t(PyObject *vv) {
|
||||||
overflow:
|
overflow:
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"long int too large to convert to int");
|
"long int too large to convert to int");
|
||||||
if (sign > 0)
|
return -1;
|
||||||
return PY_SSIZE_T_MAX;
|
|
||||||
else
|
|
||||||
return PY_SSIZE_T_MIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a Py_ssize_t from a long int object.
|
|
||||||
Returns -1 and sets an error condition if overflow occurs. */
|
|
||||||
|
|
||||||
Py_ssize_t
|
|
||||||
_PyLong_AsSsize_t(PyObject *vv)
|
|
||||||
{
|
|
||||||
Py_ssize_t x;
|
|
||||||
|
|
||||||
x = _long_as_ssize_t(vv);
|
|
||||||
if (PyErr_Occurred()) return -1;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Get a Py_ssize_t from a long int object.
|
|
||||||
Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
|
|
||||||
and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1.
|
|
||||||
On error, return -1 with an exception set.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Py_ssize_t
|
|
||||||
long_index(PyObject *vv)
|
|
||||||
{
|
|
||||||
Py_ssize_t x;
|
|
||||||
|
|
||||||
x = _long_as_ssize_t(vv);
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
/* If overflow error, ignore the error */
|
|
||||||
if (x != -1) {
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a C unsigned long int from a long int object.
|
/* Get a C unsigned long int from a long int object.
|
||||||
|
|
@ -3405,7 +3370,7 @@ static PyNumberMethods long_as_number = {
|
||||||
long_true_divide, /* nb_true_divide */
|
long_true_divide, /* nb_true_divide */
|
||||||
0, /* nb_inplace_floor_divide */
|
0, /* nb_inplace_floor_divide */
|
||||||
0, /* nb_inplace_true_divide */
|
0, /* nb_inplace_true_divide */
|
||||||
long_index, /* nb_index */
|
long_long, /* nb_index */
|
||||||
};
|
};
|
||||||
|
|
||||||
PyTypeObject PyLong_Type = {
|
PyTypeObject PyLong_Type = {
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ slice_indices(PySliceObject* self, PyObject* len)
|
||||||
{
|
{
|
||||||
Py_ssize_t ilen, start, stop, step, slicelength;
|
Py_ssize_t ilen, start, stop, step, slicelength;
|
||||||
|
|
||||||
ilen = PyInt_AsSsize_t(len);
|
ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError);
|
||||||
|
|
||||||
if (ilen == -1 && PyErr_Occurred()) {
|
if (ilen == -1 && PyErr_Occurred()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
|
|
@ -1184,14 +1184,11 @@ string_hash(PyStringObject *a)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
string_subscript(PyStringObject* self, PyObject* item)
|
string_subscript(PyStringObject* self, PyObject* item)
|
||||||
{
|
{
|
||||||
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
if (PyIndex_Check(item)) {
|
||||||
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||||
Py_ssize_t i = nb->nb_index(item);
|
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
|
|
|
||||||
|
|
@ -577,14 +577,11 @@ static PySequenceMethods tuple_as_sequence = {
|
||||||
(objobjproc)tuplecontains, /* sq_contains */
|
(objobjproc)tuplecontains, /* sq_contains */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
tuplesubscript(PyTupleObject* self, PyObject* item)
|
tuplesubscript(PyTupleObject* self, PyObject* item)
|
||||||
{
|
{
|
||||||
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
if (PyIndex_Check(item)) {
|
||||||
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||||
Py_ssize_t i = nb->nb_index(item);
|
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
|
|
|
||||||
|
|
@ -3527,7 +3527,7 @@ wrap_indexargfunc(PyObject *self, PyObject *args, void *wrapped)
|
||||||
|
|
||||||
if (!PyArg_UnpackTuple(args, "", 1, 1, &o))
|
if (!PyArg_UnpackTuple(args, "", 1, 1, &o))
|
||||||
return NULL;
|
return NULL;
|
||||||
i = PyNumber_Index(o);
|
i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
return (*func)(self, i);
|
return (*func)(self, i);
|
||||||
|
|
@ -3538,7 +3538,7 @@ getindex(PyObject *self, PyObject *arg)
|
||||||
{
|
{
|
||||||
Py_ssize_t i;
|
Py_ssize_t i;
|
||||||
|
|
||||||
i = PyNumber_Index(arg);
|
i = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
|
|
@ -4344,26 +4344,11 @@ slot_nb_nonzero(PyObject *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Py_ssize_t
|
static PyObject *
|
||||||
slot_nb_index(PyObject *self)
|
slot_nb_index(PyObject *self)
|
||||||
{
|
{
|
||||||
static PyObject *index_str;
|
static PyObject *index_str;
|
||||||
PyObject *temp = call_method(self, "__index__", &index_str, "()");
|
return call_method(self, "__index__", &index_str, "()");
|
||||||
Py_ssize_t result;
|
|
||||||
|
|
||||||
if (temp == NULL)
|
|
||||||
return -1;
|
|
||||||
if (PyInt_CheckExact(temp) || PyLong_CheckExact(temp)) {
|
|
||||||
result = temp->ob_type->tp_as_number->nb_index(temp);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyErr_Format(PyExc_TypeError,
|
|
||||||
"__index__ must return an int or a long, "
|
|
||||||
"not '%.200s'", temp->ob_type->tp_name);
|
|
||||||
result = -1;
|
|
||||||
}
|
|
||||||
Py_DECREF(temp);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5109,7 +5094,7 @@ static slotdef slotdefs[] = {
|
||||||
"oct(x)"),
|
"oct(x)"),
|
||||||
UNSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc,
|
UNSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc,
|
||||||
"hex(x)"),
|
"hex(x)"),
|
||||||
NBSLOT("__index__", nb_index, slot_nb_index, wrap_lenfunc,
|
NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc,
|
||||||
"x[y:z] <==> x[y.__index__():z.__index__()]"),
|
"x[y:z] <==> x[y.__index__():z.__index__()]"),
|
||||||
IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add,
|
IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add,
|
||||||
wrap_binaryfunc, "+"),
|
wrap_binaryfunc, "+"),
|
||||||
|
|
|
||||||
|
|
@ -6985,14 +6985,11 @@ static PySequenceMethods unicode_as_sequence = {
|
||||||
PyUnicode_Contains, /* sq_contains */
|
PyUnicode_Contains, /* sq_contains */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
unicode_subscript(PyUnicodeObject* self, PyObject* item)
|
unicode_subscript(PyUnicodeObject* self, PyObject* item)
|
||||||
{
|
{
|
||||||
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
if (PyIndex_Check(item)) {
|
||||||
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||||
Py_ssize_t i = nb->nb_index(item);
|
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
|
|
|
||||||
|
|
@ -3866,12 +3866,14 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
|
||||||
if (v != NULL) {
|
if (v != NULL) {
|
||||||
Py_ssize_t x;
|
Py_ssize_t x;
|
||||||
if (PyInt_Check(v)) {
|
if (PyInt_Check(v)) {
|
||||||
x = PyInt_AsSsize_t(v);
|
/* XXX(nnorwitz): I think PyInt_AS_LONG is correct,
|
||||||
|
however, it looks like it should be AsSsize_t.
|
||||||
|
There should be a comment here explaining why.
|
||||||
|
*/
|
||||||
|
x = PyInt_AS_LONG(v);
|
||||||
}
|
}
|
||||||
else if (v->ob_type->tp_as_number &&
|
else if (PyIndex_Check(v)) {
|
||||||
PyType_HasFeature(v->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
x = PyNumber_AsSsize_t(v, NULL);
|
||||||
&& v->ob_type->tp_as_number->nb_index) {
|
|
||||||
x = v->ob_type->tp_as_number->nb_index(v);
|
|
||||||
if (x == -1 && PyErr_Occurred())
|
if (x == -1 && PyErr_Occurred())
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -3887,10 +3889,8 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef ISINDEX
|
#undef ISINDEX
|
||||||
#define ISINDEX(x) ((x) == NULL || PyInt_Check(x) || PyLong_Check(x) || \
|
#define ISINDEX(x) ((x) == NULL || \
|
||||||
((x)->ob_type->tp_as_number && \
|
PyInt_Check(x) || PyLong_Check(x) || PyIndex_Check(x))
|
||||||
PyType_HasFeature((x)->ob_type, Py_TPFLAGS_HAVE_INDEX) \
|
|
||||||
&& (x)->ob_type->tp_as_number->nb_index))
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
|
apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue