mirror of https://github.com/python/cpython
Fix problems with memoryview object. There is still more to do to finish PEP 3118. The memory-view object needs to be fleshed out and the struct module needs to be modified.
This commit is contained in:
parent
9b30784ab2
commit
fe9bed02e4
|
@ -21,7 +21,8 @@ PyAPI_DATA(PyTypeObject) PyMemoryView_Type;
|
||||||
|
|
||||||
#define Py_END_OF_MEMORY (-1)
|
#define Py_END_OF_MEMORY (-1)
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) PyMemoryView_GetContiguous(PyObject *base, int buffertype,
|
PyAPI_FUNC(PyObject *) PyMemoryView_GetContiguous(PyObject *base,
|
||||||
|
int buffertype,
|
||||||
char fort);
|
char fort);
|
||||||
|
|
||||||
/* Return a contiguous chunk of memory representing the buffer
|
/* Return a contiguous chunk of memory representing the buffer
|
||||||
|
@ -32,17 +33,17 @@ PyAPI_FUNC(PyObject *) PyMemoryView_GetContiguous(PyObject *base, int buffertype
|
||||||
data-copying will be done.
|
data-copying will be done.
|
||||||
|
|
||||||
The buffertype argument can be PyBUF_READ, PyBUF_WRITE,
|
The buffertype argument can be PyBUF_READ, PyBUF_WRITE,
|
||||||
PyBUF_UPDATEIFCOPY to determine whether the returned buffer
|
PyBUF_SHADOW to determine whether the returned buffer
|
||||||
should be READONLY, WRITABLE, or set to update the
|
should be READONLY, WRITABLE, or set to update the
|
||||||
original buffer if a copy must be made. If buffertype is
|
original buffer if a copy must be made. If buffertype is
|
||||||
PyBUF_WRITE and the buffer is not contiguous an error will
|
PyBUF_WRITE and the buffer is not contiguous an error will
|
||||||
be raised. In this circumstance, the user can use
|
be raised. In this circumstance, the user can use
|
||||||
PyBUF_UPDATEIFCOPY to ensure that a a writable temporary
|
PyBUF_SHADOW to ensure that a a writable temporary
|
||||||
contiguous buffer is returned. The contents of this
|
contiguous buffer is returned. The contents of this
|
||||||
contiguous buffer will be copied back into the original
|
contiguous buffer will be copied back into the original
|
||||||
object after the memoryview object is deleted as long as
|
object after the memoryview object is deleted as long as
|
||||||
the original object is writable and allows setting its
|
the original object is writable and allows setting an
|
||||||
memory to "readonly". If this is not allowed by the
|
exclusive write lock. If this is not allowed by the
|
||||||
original object, then a BufferError is raised.
|
original object, then a BufferError is raised.
|
||||||
|
|
||||||
If the object is multi-dimensional and if fortran is 'F',
|
If the object is multi-dimensional and if fortran is 'F',
|
||||||
|
|
|
@ -164,7 +164,7 @@ typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
|
||||||
#define PyBUF_WRITABLE 0x0002
|
#define PyBUF_WRITABLE 0x0002
|
||||||
/* we used to include an E, backwards compatible alias */
|
/* we used to include an E, backwards compatible alias */
|
||||||
#define PyBUF_WRITEABLE PyBUF_WRITABLE
|
#define PyBUF_WRITEABLE PyBUF_WRITABLE
|
||||||
#define PyBUF_LOCKDATA 0x0004
|
#define PyBUF_LOCK 0x0004
|
||||||
#define PyBUF_FORMAT 0x0008
|
#define PyBUF_FORMAT 0x0008
|
||||||
#define PyBUF_ND 0x0010
|
#define PyBUF_ND 0x0010
|
||||||
#define PyBUF_STRIDES (0x0020 | PyBUF_ND)
|
#define PyBUF_STRIDES (0x0020 | PyBUF_ND)
|
||||||
|
@ -175,19 +175,25 @@ typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
|
||||||
|
|
||||||
#define PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE)
|
#define PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE)
|
||||||
#define PyBUF_CONTIG_RO (PyBUF_ND)
|
#define PyBUF_CONTIG_RO (PyBUF_ND)
|
||||||
#define PyBUF_CONTIG_LCK (PyBUF_ND | PyBUF_LOCKDATA)
|
#define PyBUF_CONTIG_LCK (PyBUF_ND | PyBUF_LOCK)
|
||||||
|
#define PyBUF_CONTIG_XLCK (PyBUF_ND | PyBUF_LOCK | PyBUF_WRITABLE)
|
||||||
|
|
||||||
#define PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE)
|
#define PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE)
|
||||||
#define PyBUF_STRIDED_RO (PyBUF_STRIDES)
|
#define PyBUF_STRIDED_RO (PyBUF_STRIDES)
|
||||||
#define PyBUF_STRIDED_LCK (PyBUF_STRIDES | PyBUF_LOCKDATA)
|
#define PyBUF_STRIDED_LCK (PyBUF_STRIDES | PyBUF_LOCK)
|
||||||
|
#define PyBUF_STRIDED_XLCK (PyBUF_STRIDES | PyBUF_LOCK | PyBUF_WRITABLE)
|
||||||
|
|
||||||
#define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT)
|
#define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT)
|
||||||
#define PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT)
|
#define PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT)
|
||||||
#define PyBUF_RECORDS_LCK (PyBUF_STRIDES | PyBUF_LOCKDATA | PyBUF_FORMAT)
|
#define PyBUF_RECORDS_LCK (PyBUF_STRIDES | PyBUF_LOCK | PyBUF_FORMAT)
|
||||||
|
#define PyBUF_RECORDS_XLCK (PyBUF_STRIDES | PyBUF_LOCK | PyBUF_WRITABLE \
|
||||||
|
| PyBUF_FORMAT)
|
||||||
|
|
||||||
#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT)
|
#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT)
|
||||||
#define PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT)
|
#define PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT)
|
||||||
#define PyBUF_FULL_LCK (PyBUF_INDIRECT | PyBUF_LOCKDATA | PyBUF_FORMAT)
|
#define PyBUF_FULL_LCK (PyBUF_INDIRECT | PyBUF_LOCK | PyBUF_FORMAT)
|
||||||
|
#define PyBUF_FULL_XLCK (PyBUF_INDIRECT | PyBUF_LOCK | PyBUF_WRITABLE \
|
||||||
|
| PyBUF_FORMAT)
|
||||||
|
|
||||||
|
|
||||||
#define PyBUF_READ 0x100
|
#define PyBUF_READ 0x100
|
||||||
|
|
|
@ -653,14 +653,14 @@ PyBuffer_FillInfo(Py_buffer *view, void *buf, Py_ssize_t len,
|
||||||
int readonly, int flags)
|
int readonly, int flags)
|
||||||
{
|
{
|
||||||
if (view == NULL) return 0;
|
if (view == NULL) return 0;
|
||||||
if (((flags & PyBUF_LOCKDATA) == PyBUF_LOCKDATA) &&
|
if (((flags & PyBUF_LOCK) == PyBUF_LOCK) &&
|
||||||
readonly != -1) {
|
readonly >= 0) {
|
||||||
PyErr_SetString(PyExc_BufferError,
|
PyErr_SetString(PyExc_BufferError,
|
||||||
"Cannot make this object read-only.");
|
"Cannot lock this object.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) &&
|
if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) &&
|
||||||
readonly == 1) {
|
(readonly == 1)) {
|
||||||
PyErr_SetString(PyExc_BufferError,
|
PyErr_SetString(PyExc_BufferError,
|
||||||
"Object is not writable.");
|
"Object is not writable.");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -196,7 +196,9 @@ _indirect_copy_nd(char *dest, Py_buffer *view, char fort)
|
||||||
a contiguous buffer if it is not. The view will point to
|
a contiguous buffer if it is not. The view will point to
|
||||||
the shadow buffer which can be written to and then
|
the shadow buffer which can be written to and then
|
||||||
will be copied back into the other buffer when the memory
|
will be copied back into the other buffer when the memory
|
||||||
view is de-allocated.
|
view is de-allocated. While the shadow buffer is
|
||||||
|
being used, it will have an exclusive write lock on
|
||||||
|
the original buffer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
@ -224,7 +226,7 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
|
||||||
flags = PyBUF_FULL;
|
flags = PyBUF_FULL;
|
||||||
break;
|
break;
|
||||||
case PyBUF_SHADOW:
|
case PyBUF_SHADOW:
|
||||||
flags = PyBUF_FULL_LCK;
|
flags = PyBUF_FULL_XLCK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,10 +433,6 @@ memory_dealloc(PyMemoryViewObject *self)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
memory_repr(PyMemoryViewObject *self)
|
memory_repr(PyMemoryViewObject *self)
|
||||||
{
|
{
|
||||||
/* XXX(nnorwitz): the code should be different or remove condition. */
|
|
||||||
if (self->base == NULL)
|
|
||||||
return PyUnicode_FromFormat("<memory at %p>", self);
|
|
||||||
else
|
|
||||||
return PyUnicode_FromFormat("<memory at %p>", self);
|
return PyUnicode_FromFormat("<memory at %p>", self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,6 +500,14 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
|
||||||
/* Return a bytes object */
|
/* Return a bytes object */
|
||||||
char *ptr;
|
char *ptr;
|
||||||
ptr = (char *)view->buf;
|
ptr = (char *)view->buf;
|
||||||
|
if (result < 0) {
|
||||||
|
result += view->shape[0];
|
||||||
|
}
|
||||||
|
if ((result < 0) || (result > view->shape[0])) {
|
||||||
|
PyErr_SetString(PyExc_IndexError,
|
||||||
|
"index out of bounds");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (view->strides == NULL)
|
if (view->strides == NULL)
|
||||||
ptr += view->itemsize * result;
|
ptr += view->itemsize * result;
|
||||||
else
|
else
|
||||||
|
@ -517,14 +523,20 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
|
||||||
/* Return a new memory-view object */
|
/* Return a new memory-view object */
|
||||||
Py_buffer newview;
|
Py_buffer newview;
|
||||||
memset(&newview, 0, sizeof(newview));
|
memset(&newview, 0, sizeof(newview));
|
||||||
|
/* XXX: This needs to be fixed so it
|
||||||
|
actually returns a sub-view
|
||||||
|
*/
|
||||||
return PyMemoryView_FromMemory(&newview);
|
return PyMemoryView_FromMemory(&newview);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Need to support getting a sliced view */
|
||||||
Py_INCREF(Py_NotImplemented);
|
Py_INCREF(Py_NotImplemented);
|
||||||
return Py_NotImplemented;
|
return Py_NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Need to support assigning memory if we can */
|
||||||
static int
|
static int
|
||||||
memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
|
memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue