Author: Matti Picus <[email protected]>
Branch:
Changeset: r94150:abd1818fcde4
Date: 2018-03-28 00:02 +0300
http://bitbucket.org/pypy/pypy/changeset/abd1818fcde4/
Log: test, fix for PySequence_ITEM accessing sq_item, not mp_subscr. Both
are __getitem__, the second takes precedence
diff --git a/pypy/module/cpyext/sequence.py b/pypy/module/cpyext/sequence.py
--- a/pypy/module/cpyext/sequence.py
+++ b/pypy/module/cpyext/sequence.py
@@ -5,7 +5,8 @@
from pypy.objspace.std.listobject import (
ListStrategy, UNROLL_CUTOFF, W_ListObject, ObjectListStrategy)
from pypy.module.cpyext.api import (
- cpython_api, CANNOT_FAIL, CONST_STRING, Py_ssize_t, PyObject, PyObjectP)
+ cpython_api, CANNOT_FAIL, CONST_STRING, Py_ssize_t, PyObject, PyObjectP,
+ generic_cpy_call)
from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
from pypy.module.cpyext.pyobject import as_pyobj, incref
from rpython.rtyper.lltypesystem import rffi, lltype
@@ -145,21 +146,26 @@
# XXX we should call Py*_GET_ITEM() instead of Py*_GetItem()
# from here, but we cannot because we are also called from
# PySequence_GetItem()
+ py_obj = as_pyobj(space, w_obj)
if isinstance(w_obj, tupleobject.W_TupleObject):
from pypy.module.cpyext.tupleobject import PyTuple_GetItem
- py_obj = as_pyobj(space, w_obj)
py_res = PyTuple_GetItem(space, py_obj, i)
incref(space, py_res)
keepalive_until_here(w_obj)
return py_res
if isinstance(w_obj, W_ListObject):
from pypy.module.cpyext.listobject import PyList_GetItem
- py_obj = as_pyobj(space, w_obj)
py_res = PyList_GetItem(space, py_obj, i)
incref(space, py_res)
keepalive_until_here(w_obj)
return py_res
- return make_ref(space, space.getitem(w_obj, space.newint(i)))
+
+ as_sequence = py_obj.c_ob_type.c_tp_as_sequence
+ if not as_sequence or not as_sequence.c_sq_item:
+ raise oefmt(space.w_TypeError,
+ "'%T' object does not support indexing", w_obj)
+ ret = generic_cpy_call(space, as_sequence.c_sq_item, w_obj, i)
+ return make_ref(space, ret)
@cpython_api([PyObject, Py_ssize_t], PyObject, result_is_ll=True)
def PySequence_GetItem(space, w_obj, i):
diff --git a/pypy/module/cpyext/test/array.c b/pypy/module/cpyext/test/array.c
--- a/pypy/module/cpyext/test/array.c
+++ b/pypy/module/cpyext/test/array.c
@@ -2202,6 +2202,16 @@
Py_RETURN_NONE;
};
+static PyObject *
+getitem(PyObject* self, PyObject * args) {
+ PyObject * obj;
+ int i;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &i)) {
+ return NULL;
+ }
+ return PySequence_ITEM(obj, i);
+}
+
PyDoc_STRVAR(module_doc,
"This module defines an object type which can efficiently represent\n\
an array of basic values: characters, integers, floating point\n\
@@ -2491,6 +2501,7 @@
{"get_releasebuffer_cnt", (PyCFunction)get_releasebuffer_cnt,
METH_NOARGS, NULL},
{"create_and_release_buffer", (PyCFunction)create_and_release_buffer,
METH_O, NULL},
{"same_dealloc", (PyCFunction)same_dealloc, METH_VARARGS, NULL},
+ {"getitem", (PyCFunction)getitem, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL} /* Sentinel */
};
diff --git a/pypy/module/cpyext/test/test_arraymodule.py
b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -172,3 +172,15 @@
fd = BytesIO()
# only test that it works
fd.write(a)
+
+ def test_getitem_via_PySequence_GetItem(self):
+ module = self.import_module(name='array')
+ a = module.array('i', range(10))
+ # call via tp_as_mapping.mp_subscript
+ assert 5 == a[-5]
+ # PySequence_ITEM used to call space.getitem() which
+ # prefers tp_as_mapping.mp_subscript over tp_as_sequence.sq_item
+ # Now fixed so this test raises (array_item does not add len(a),
+ # array_subscr does)
+ raises(IndexError, module.getitem, a, -5)
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit