mirror of https://github.com/python/cpython
Issue #14181: Test creating memoryviews from a static exporter with both
view.obj==NULL and view.obj==base.
This commit is contained in:
parent
8d217c6a71
commit
bf6c7eca43
|
@ -3515,6 +3515,100 @@ class TestBufferProtocol(unittest.TestCase):
|
||||||
del y, z
|
del y, z
|
||||||
self.assertEqual(m[1:3], x[1:3])
|
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):
|
def test_issue_7385(self):
|
||||||
x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
|
x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
|
||||||
self.assertRaises(BufferError, memoryview, x)
|
self.assertRaises(BufferError, memoryview, x)
|
||||||
|
|
|
@ -2602,6 +2602,126 @@ static PyTypeObject NDArray_Type = {
|
||||||
ndarray_new, /* tp_new */
|
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[] = {
|
static struct PyMethodDef _testbuffer_functions[] = {
|
||||||
{"slice_indices", slice_indices, METH_VARARGS, NULL},
|
{"slice_indices", slice_indices, METH_VARARGS, NULL},
|
||||||
|
@ -2634,10 +2754,14 @@ PyInit__testbuffer(void)
|
||||||
if (m == NULL)
|
if (m == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Py_TYPE(&NDArray_Type)=&PyType_Type;
|
Py_TYPE(&NDArray_Type) = &PyType_Type;
|
||||||
Py_INCREF(&NDArray_Type);
|
Py_INCREF(&NDArray_Type);
|
||||||
PyModule_AddObject(m, "ndarray", (PyObject *)&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");
|
structmodule = PyImport_ImportModule("struct");
|
||||||
if (structmodule == NULL)
|
if (structmodule == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue