Author: Matti Picus <[email protected]>
Branch:
Changeset: r86125:72d14a4de609
Date: 2016-08-10 07:01 +0300
http://bitbucket.org/pypy/pypy/changeset/72d14a4de609/
Log: test, fix PySequence_Fast getslice; remove outdated document
diff --git a/pypy/module/cpyext/c-api.txt b/pypy/module/cpyext/c-api.txt
deleted file mode 100644
--- a/pypy/module/cpyext/c-api.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-Reference Count
-===============
-
-XXX
-
-Borrowed References
-===================
-
-XXX
-
-PyStringObject support
-======================
-
-The problem
------------
-
-PyString_AsString() returns a (non-movable) pointer to the underlying
-buffer, whereas pypy strings are movable. C code may temporarily
-store this address and use it, as long as it owns a reference to the
-PyObject. There is no "release" function to specify that the pointer
-is not needed any more.
-
-Note that the pointer may be used to fill the initial value of
-string. This is valid only when the string was just allocated, and is
-not used elsewhere.
-
-Proposed solution
------------------
-
-Our emulation of the PyStringObject contains an additional member: a
-pointer to a char buffer; it may be NULL.
-
-- A string allocated by pypy will be converted into a PyStringObject
- with a NULL buffer. When PyString_AsString() is called, memory is
- allocated (with flavor='raw') and content is copied.
-
-- A string allocated with PyString_FromStringAndSize(NULL, size) will
- allocate a buffer with the specified size, but the reference won't
- be stored in the global map py_objects_r2w; there won't be a
- corresponding object in pypy. When from_ref() or Py_INCREF() is
- called, the pypy string is created, and added in py_objects_r2w.
- The buffer is then supposed to be immutable.
-
-- _PyString_Resize works only on not-yet-pypy'd strings, and returns a
- similar object.
-
-- PyString_Size don't need to force the object. (in this case, another
- "size" member is needed)
-
-- There could be an (expensive!) check in from_ref() that the buffer
- still corresponds to the pypy gc-managed string.
-
-PySequence_Fast support
-======================
-There are five functions for fast sequence access offered by the CPython API:
-
-PyObject* PySequence_Fast(PyObject *o, const char *m)
-
-PyObject* PySequence_Fast_GET_ITEM( PyObject *o, int i)
-
-PyObject** PySequence_Fast_ITEMS( PyObject *o)
-
-PyObject* PySequence_ITEM( PyObject *o, int i)
-
-int PySequence_Fast_GET_SIZE( PyObject *o)
-
-PyPy supports four of these, but does not support PySequence_Fast_ITEMS.
-(Various ways to support PySequence_Fast_ITEMS were considered. They all had
-two things in common: they would have taken a lot of work, and they would have
-resulted in incomplete semantics or in poor performance. We decided that a slow
-implementation of PySequence_Fast_ITEMS was not very useful.)
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
@@ -10,7 +10,7 @@
from pypy.objspace.std import tupleobject
from pypy.module.cpyext.tupleobject import PyTuple_Check, PyTuple_SetItem
-from pypy.module.cpyext.object import Py_IncRef, Py_DecRef
+from pypy.module.cpyext.pyobject import decref
from pypy.module.cpyext.dictobject import PyDict_Check
@@ -252,7 +252,7 @@
def setitem(self, w_list, index, w_obj):
storage = self.unerase(w_list.lstorage)
index = self._check_index(index, storage._length)
- Py_DecRef(w_list.space, storage._elems[index])
+ decref(w_list.space, storage._elems[index])
storage._elems[index] = make_ref(w_list.space, w_obj)
def length(self, w_list):
@@ -264,9 +264,8 @@
return storage._elems
def getslice(self, w_list, start, stop, step, length):
- #storage = self.unerase(w_list.lstorage)
- raise oefmt(w_list.space.w_NotImplementedError,
- "settting a slice of a PySequence_Fast is not supported")
+ w_list.switch_to_object_strategy()
+ return w_list.strategy.getslice(w_list, start, stop, step, length)
def getitems(self, w_list):
# called when switching list strategy, so convert storage
@@ -389,5 +388,5 @@
def __del__(self):
for i in range(self._length):
- Py_DecRef(self.space, self._elems[i])
+ decref(self.space, self._elems[i])
lltype.free(self._elems, flavor='raw')
diff --git a/pypy/module/cpyext/test/test_sequence.py
b/pypy/module/cpyext/test/test_sequence.py
--- a/pypy/module/cpyext/test/test_sequence.py
+++ b/pypy/module/cpyext/test/test_sequence.py
@@ -78,6 +78,17 @@
assert api.PySequence_SetSlice(w_t, 1, 1, space.wrap((3,))) == 0
assert space.eq_w(w_t, space.wrap([1, 3, 5]))
+ def test_get_slice_fast(self, space, api):
+ w_t = space.wrap([1, 2, 3, 4, 5])
+ api.PySequence_Fast(w_t, "foo") # converts
+ assert space.unwrap(api.PySequence_GetSlice(w_t, 2, 4)) == [3, 4]
+ assert space.unwrap(api.PySequence_GetSlice(w_t, 1, -1)) == [2, 3, 4]
+
+ assert api.PySequence_DelSlice(w_t, 1, 4) == 0
+ assert space.eq_w(w_t, space.wrap([1, 5]))
+ assert api.PySequence_SetSlice(w_t, 1, 1, space.wrap((3,))) == 0
+ assert space.eq_w(w_t, space.wrap([1, 3, 5]))
+
def test_iter(self, space, api):
w_t = space.wrap((1, 2))
w_iter = api.PySeqIter_New(w_t)
@@ -226,18 +237,33 @@
assert space.int_w(space.len(w_l)) == 10
-class XAppTestSequenceObject(AppTestCpythonExtensionBase):
- def test_sequenceobject(self):
+class AppTestSequenceObject(AppTestCpythonExtensionBase):
+ def test_fast(self):
module = self.import_extension('foo', [
("test_fast_sequence", "METH_VARARGS",
"""
- PyObject * o = PyTuple_GetItem(args, 0);
+ int size, i;
+ PyTypeObject * common_type;
+ PyObject *foo, **objects;
+ PyObject * seq = PyTuple_GetItem(args, 0);
/* XXX assert it is a tuple */
- PyObject *foo = PySequence_Fast(o, "some string");
- PyObject ** res = PySequence_Fast_ITEMS(foo);
- /* XXX do some kind of test on res */
- /* XXX now what? who manages res's refcount? */
+ if (seq == NULL)
+ Py_RETURN_NONE;
+ foo = PySequence_Fast(seq, "some string");
+ objects = PySequence_Fast_ITEMS(foo);
+ size = PySequence_Fast_GET_SIZE(seq);
+ common_type = size > 0 ? Py_TYPE(objects[0]) : NULL;
+ for (i = 1; i < size; ++i) {
+ if (Py_TYPE(objects[i]) != common_type) {
+ common_type = NULL;
+ break;
+ }
+ }
+ Py_DECREF(foo);
+ Py_DECREF(common_type);
return PyBool_FromLong(1);
""")])
- assert module.test_fast_sequence([1, 2, 3, 4])
+ s = [1, 2, 3, 4]
+ assert module.test_fast_sequence(s[0:-1])
+ assert module.test_fast_sequence(s[::-1])
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit