summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Krah <skrah@bytereef.org>2012-03-05 13:37:34 (GMT)
committerStefan Krah <skrah@bytereef.org>2012-03-05 13:37:34 (GMT)
commitbf6c7eca43d7c7d80525c97af08aef52ec81e4a1 (patch)
tree58b43adc5ebdc5faac233cf640ef6ce1f8332967
parent8d217c6a7103b51cfbe85b2b4ad509cb6ebeb95b (diff)
downloadcpython-bf6c7eca43d7c7d80525c97af08aef52ec81e4a1.zip
cpython-bf6c7eca43d7c7d80525c97af08aef52ec81e4a1.tar.gz
cpython-bf6c7eca43d7c7d80525c97af08aef52ec81e4a1.tar.bz2
Issue #14181: Test creating memoryviews from a static exporter with both
view.obj==NULL and view.obj==base.
-rw-r--r--Lib/test/test_buffer.py94
-rw-r--r--Modules/_testbuffer.c126
2 files changed, 219 insertions, 1 deletions
diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py
index 8a8d55d..533338e 100644
--- a/Lib/test/test_buffer.py
+++ b/Lib/test/test_buffer.py
@@ -3515,6 +3515,100 @@ class TestBufferProtocol(unittest.TestCase):
del y, z
self.assertEqual(m[1:3], x[1:3])
+ def test_memoryview_from_static_exporter(self):
+
+ fmt = 'B'
+ lst = [0,1,2,3,4,5,6,7,8,9,10,11]
+
+ # exceptions
+ self.assertRaises(TypeError, staticarray, 1, 2, 3)
+
+ # view.obj==x
+ x = staticarray()
+ y = memoryview(x)
+ self.verify(y, obj=x,
+ itemsize=1, fmt=fmt, readonly=1,
+ ndim=1, shape=[12], strides=[1],
+ lst=lst)
+ for i in range(12):
+ self.assertEqual(y[i], i)
+ del x
+ del y
+
+ x = staticarray()
+ y = memoryview(x)
+ del y
+ del x
+
+ x = staticarray()
+ y = ndarray(x, getbuf=PyBUF_FULL_RO)
+ z = ndarray(y, getbuf=PyBUF_FULL_RO)
+ m = memoryview(z)
+ self.assertIs(y.obj, x)
+ self.assertIs(m.obj, z)
+ self.verify(m, obj=z,
+ itemsize=1, fmt=fmt, readonly=1,
+ ndim=1, shape=[12], strides=[1],
+ lst=lst)
+ del x, y, z, m
+
+ x = staticarray()
+ y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
+ z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
+ m = memoryview(z)
+ self.assertIs(y.obj, x)
+ self.assertIs(z.obj, x)
+ self.assertIs(m.obj, x)
+ self.verify(m, obj=x,
+ itemsize=1, fmt=fmt, readonly=1,
+ ndim=1, shape=[12], strides=[1],
+ lst=lst)
+ del x, y, z, m
+
+ # view.obj==NULL
+ x = staticarray(legacy_mode=True)
+ y = memoryview(x)
+ self.verify(y, obj=None,
+ itemsize=1, fmt=fmt, readonly=1,
+ ndim=1, shape=[12], strides=[1],
+ lst=lst)
+ for i in range(12):
+ self.assertEqual(y[i], i)
+ del x
+ del y
+
+ x = staticarray(legacy_mode=True)
+ y = memoryview(x)
+ del y
+ del x
+
+ x = staticarray(legacy_mode=True)
+ y = ndarray(x, getbuf=PyBUF_FULL_RO)
+ z = ndarray(y, getbuf=PyBUF_FULL_RO)
+ m = memoryview(z)
+ self.assertIs(y.obj, None)
+ self.assertIs(m.obj, z)
+ self.verify(m, obj=z,
+ itemsize=1, fmt=fmt, readonly=1,
+ ndim=1, shape=[12], strides=[1],
+ lst=lst)
+ del x, y, z, m
+
+ x = staticarray(legacy_mode=True)
+ y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
+ z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
+ m = memoryview(z)
+ # Clearly setting view.obj==NULL is inferior, since it
+ # messes up the redirection chain:
+ self.assertIs(y.obj, None)
+ self.assertIs(z.obj, y)
+ self.assertIs(m.obj, y)
+ self.verify(m, obj=y,
+ itemsize=1, fmt=fmt, readonly=1,
+ ndim=1, shape=[12], strides=[1],
+ lst=lst)
+ del x, y, z, m
+
def test_issue_7385(self):
x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
self.assertRaises(BufferError, memoryview, x)
diff --git a/Modules/_testbuffer.c b/Modules/_testbuffer.c
index d1bf258..63f6b53 100644
--- a/Modules/_testbuffer.c
+++ b/Modules/_testbuffer.c
@@ -2602,6 +2602,126 @@ static PyTypeObject NDArray_Type = {
ndarray_new, /* tp_new */
};
+/**************************************************************************/
+/* StaticArray Object */
+/**************************************************************************/
+
+static PyTypeObject StaticArray_Type;
+
+typedef struct {
+ PyObject_HEAD
+ int legacy_mode; /* if true, use the view.obj==NULL hack */
+} StaticArrayObject;
+
+static char static_mem[12] = {0,1,2,3,4,5,6,7,8,9,10,11};
+static Py_ssize_t static_shape[1] = {12};
+static Py_ssize_t static_strides[1] = {1};
+static Py_buffer static_buffer = {
+ static_mem, /* buf */
+ NULL, /* obj */
+ 12, /* len */
+ 1, /* itemsize */
+ 1, /* readonly */
+ 1, /* ndim */
+ "B", /* format */
+ static_shape, /* shape */
+ static_strides, /* strides */
+ NULL, /* suboffsets */
+ NULL /* internal */
+};
+
+static PyObject *
+staticarray_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ return (PyObject *)PyObject_New(StaticArrayObject, &StaticArray_Type);
+}
+
+static int
+staticarray_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ StaticArrayObject *a = (StaticArrayObject *)self;
+ static char *kwlist[] = {
+ "legacy_mode", NULL
+ };
+ PyObject *legacy_mode = Py_False;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &legacy_mode))
+ return -1;
+
+ a->legacy_mode = (legacy_mode != Py_False);
+ return 0;
+}
+
+static void
+staticarray_dealloc(StaticArrayObject *self)
+{
+ PyObject_Del(self);
+}
+
+/* Return a buffer for a PyBUF_FULL_RO request. Flags are not checked,
+ which makes this object a non-compliant exporter! */
+static int
+staticarray_getbuf(StaticArrayObject *self, Py_buffer *view, int flags)
+{
+ *view = static_buffer;
+
+ if (self->legacy_mode) {
+ view->obj = NULL; /* Don't use this in new code. */
+ }
+ else {
+ view->obj = (PyObject *)self;
+ Py_INCREF(view->obj);
+ }
+
+ return 0;
+}
+
+static PyBufferProcs staticarray_as_buffer = {
+ (getbufferproc)staticarray_getbuf, /* bf_getbuffer */
+ NULL, /* bf_releasebuffer */
+};
+
+static PyTypeObject StaticArray_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "staticarray", /* Name of this type */
+ sizeof(StaticArrayObject), /* Basic object size */
+ 0, /* Item size for varobject */
+ (destructor)staticarray_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ &staticarray_as_buffer, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ staticarray_init, /* tp_init */
+ 0, /* tp_alloc */
+ staticarray_new, /* tp_new */
+};
+
static struct PyMethodDef _testbuffer_functions[] = {
{"slice_indices", slice_indices, METH_VARARGS, NULL},
@@ -2634,10 +2754,14 @@ PyInit__testbuffer(void)
if (m == NULL)
return NULL;
- Py_TYPE(&NDArray_Type)=&PyType_Type;
+ Py_TYPE(&NDArray_Type) = &PyType_Type;
Py_INCREF(&NDArray_Type);
PyModule_AddObject(m, "ndarray", (PyObject *)&NDArray_Type);
+ Py_TYPE(&StaticArray_Type) = &PyType_Type;
+ Py_INCREF(&StaticArray_Type);
+ PyModule_AddObject(m, "staticarray", (PyObject *)&StaticArray_Type);
+
structmodule = PyImport_ImportModule("struct");
if (structmodule == NULL)
return NULL;