Py_INCREF(r);
return r;
}
- } else { /* inlined PySequence_GetItem() + special cased length overflow */
+ } else {
+ // inlined PySequence_GetItem() + special cased length overflow
PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
if (likely(m && m->sq_item)) {
if (wraparound && unlikely(i < 0) && likely(m->sq_length)) {
__Pyx_SetItemInt_Fast(o, i, v, is_list, wraparound, boundscheck) : \
__Pyx_SetItemInt_Generic(o, to_py_func(i), v))
+static CYTHON_INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v);
+static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v,
+ int is_list, int wraparound, int boundscheck);
+
+/////////////// SetItemInt ///////////////
+
static CYTHON_INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
int r;
if (!j) return -1;
Py_DECREF(old);
return 1;
}
- } else { /* inlined PySequence_SetItem() */
+ } else {
+ // inlined PySequence_SetItem() + special cased length overflow
PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
if (likely(m && m->sq_ass_item)) {
if (wraparound && unlikely(i < 0) && likely(m->sq_length)) {
Py_ssize_t l = m->sq_length(o);
- if (unlikely(l < 0)) return -1;
- i += l;
+ if (likely(l >= 0)) {
+ i += l;
+ } else {
+ // if length > max(Py_ssize_t), maybe the object can wrap around itself?
+ if (PyErr_ExceptionMatches(PyExc_OverflowError))
+ PyErr_Clear();
+ else
+ return -1;
+ }
}
return m->sq_ass_item(o, i, v);
}
__Pyx_DelItemInt_Fast(o, i, is_list, wraparound) : \
__Pyx_DelItem_Generic(o, to_py_func(i)))
+static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j);
+static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i,
+ CYTHON_UNUSED int is_list, int wraparound);
+
+/////////////// DelItemInt ///////////////
+
static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
int r;
if (!j) return -1;
return PySequence_DelItem(o, i);
}
#else
- /* inlined PySequence_DelItem() */
+ // inlined PySequence_DelItem() + special cased length overflow
PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
if (likely(m && m->sq_ass_item)) {
if (wraparound && unlikely(i < 0) && likely(m->sq_length)) {
Py_ssize_t l = m->sq_length(o);
- if (unlikely(l < 0)) return -1;
- i += l;
+ if (likely(l >= 0)) {
+ i += l;
+ } else {
+ // if length > max(Py_ssize_t), maybe the object can wrap around itself?
+ if (PyErr_ExceptionMatches(PyExc_OverflowError))
+ PyErr_Clear();
+ else
+ return -1;
+ }
}
return m->sq_ass_item(o, i, (PyObject *)NULL);
}
TypeError: 'int' object ...
"""
+cdef Py_ssize_t maxsize
+
import sys
if sys.version_info < (2,5):
__doc__ = __doc__.replace(u"'int' object ...", u'unsubscriptable object')
+ maxsize = min(sys.maxint, 2**31-1)
+else:
+ maxsize = getattr(sys, 'maxsize', getattr(sys, 'maxint', None))
-cdef Py_ssize_t maxsize = getattr(sys, 'maxsize', getattr(sys, 'maxint', None))
py_maxsize = maxsize
import cython
class LargeIndexable(object):
+ expected = None
+
def __len__(self):
raise OverflowError
def __getitem__(self, index):
return index
+ def __setitem__(self, index, value):
+ assert index == value == self.expected
+ self.expected = None
+
+ def __delitem__(self, index):
+ assert self.expected == index
+ self.expected = None
+
def test_large_indexing(obj):
"""
obj[maxsize], obj[-maxsize],
#obj[maxsize*2], obj[-maxsize*2] # FIXME!
)
+
+
+def del_large_index(obj, Py_ssize_t index):
+ """
+ >>> obj = LargeIndexable()
+ >>> del_large_index(obj, 0)
+ >>> del_large_index(obj, 1)
+ >>> del_large_index(obj, -1)
+ >>> del_large_index(obj, py_maxsize)
+ >>> del_large_index(obj, -py_maxsize)
+ """
+ obj.expected = index
+ del obj[index]
+ assert obj.expected is None
+
+
+def set_large_index(obj, Py_ssize_t index):
+ """
+ >>> obj = LargeIndexable()
+ >>> set_large_index(obj, 0)
+ >>> set_large_index(obj, 1)
+ >>> set_large_index(obj, -1)
+ >>> set_large_index(obj, py_maxsize)
+ >>> set_large_index(obj, -py_maxsize)
+ """
+ obj.expected = index
+ obj[index] = index
+ assert obj.expected is None