[pypy-svn] pypy pyarg-parsebuffer: save the input object and incref it
exarkun
commits-noreply at bitbucket.org
Mon Apr 18 23:54:18 CEST 2011
Author: Jean-Paul Calderone <exarkun at twistedmatrix.com>
Branch: pyarg-parsebuffer
Changeset: r43459:a9e9d816a5cf
Date: 2011-04-18 17:29 -0400
http://bitbucket.org/pypy/pypy/changeset/a9e9d816a5cf/
Log: save the input object and incref it
diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -4,7 +4,7 @@
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import Py_LT, Py_LE, Py_NE, Py_EQ,\
- Py_GE, Py_GT, fopen, fclose, fwrite
+ Py_GE, Py_GT, Py_buffer, fopen, fclose, fwrite
from pypy.tool.udir import udir
class TestObject(BaseApiTest):
@@ -267,3 +267,55 @@
""")])
assert module.dump(self.tmpname, None)
assert open(self.tmpname).read() == 'None'
+
+
+
+class AppTestPyBuffer_FillInfo(AppTestCpythonExtensionBase):
+ """
+ PyBuffer_FillInfo populates the fields of a Py_buffer from its arguments.
+ """
+ def test_nullObject(self):
+ """
+ PyBuffer_FillInfo populates the C{buf}, C{length}, and C{obj} fields of
+ the Py_buffer passed to it.
+ """
+ module = self.import_extension('foo', [
+ ("fillinfo", "METH_VARARGS",
+ """
+ Py_buffer buf;
+ PyObject *str = PyString_FromString("hello, world.");
+ PyObject *result;
+
+ if (PyBuffer_FillInfo(&buf, str, PyString_AsString(str), 13, 0, 0)) {
+ return NULL;
+ }
+
+ /* Get rid of our own reference to the object, but the Py_buffer should
+ * still have a reference.
+ */
+ Py_DECREF(str);
+
+ /* Give back a new string to the caller, constructed from data in the
+ * Py_buffer. It better still be valid.
+ */
+ if (!(result = PyString_FromStringAndSize(buf.buf, buf.len))) {
+ return NULL;
+ }
+
+ /* Now the data in the Py_buffer is really no longer needed, get rid of it
+ *(could use PyBuffer_Release here, but that would drag in more code than
+ * necessary).
+ */
+ Py_DECREF(buf.obj);
+
+ /* Py_DECREF can't directly signal error to us, but if it makes a reference
+ * count go negative, it will set an error.
+ */
+ if (PyErr_Occurred()) {
+ return NULL;
+ }
+
+ return result;
+ """)])
+ result = module.fillinfo()
+ assert "hello, world." == result
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -474,6 +474,9 @@
def PyBuffer_FillInfo(space, view, obj, buf, length, readonly, flags):
view.c_buf = buf
view.c_len = length
+ view.c_obj = obj
+ Py_IncRef(space, obj)
+ return 0
@cpython_api([lltype.Ptr(Py_buffer)], lltype.Void, error=CANNOT_FAIL)
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -418,7 +418,7 @@
Py_buffer = cpython_struct(
"Py_buffer", (
('buf', rffi.VOIDP),
- # ('obj', PyObject),
+ ('obj', PyObject),
('len', Py_ssize_t),
# ('itemsize', Py_ssize_t),
diff --git a/pypy/module/cpyext/test/test_getargs.py b/pypy/module/cpyext/test/test_getargs.py
--- a/pypy/module/cpyext/test/test_getargs.py
+++ b/pypy/module/cpyext/test/test_getargs.py
@@ -123,4 +123,4 @@
}
return PyString_FromStringAndSize(buf.buf, buf.len);
''')
- assert pybuffer('foo\0bar\0baz') == 'foo\0bar\0baz'
+ assert 'foo\0bar\0baz' == pybuffer('foo\0bar\0baz')
More information about the Pypy-commit
mailing list