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

Reply via email to