Skip to content

Commit 62641e9

Browse files
committed
Issue 6329: Fix iteration for memoryviews.
1 parent ef087da commit 62641e9

File tree

3 files changed

+60
-32
lines changed

3 files changed

+60
-32
lines changed

Lib/test/test_memoryview.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ def test_getitem(self):
4848
for tp in self._types:
4949
self.check_getitem_with_type(tp)
5050

51+
def test_iter(self):
52+
for tp in self._types:
53+
b = tp(self._source)
54+
m = self._view(b)
55+
self.assertEqual(list(m), [m[i] for i in range(len(m))])
56+
5157
def test_setitem_readonly(self):
5258
if not self.ro_type:
5359
return

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 1
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #6329: Fixed iteration for memoryview objects (it was being blocked
16+
because it wasn't recognized as a sequence).
17+
1518
- Issue #6289: Encoding errors from compile() were being masked.
1619

1720
- When no module is given in a relative import, the module field of the

Objects/memoryobject.c

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,49 @@ memory_length(PyMemoryViewObject *self)
513513
return get_shape0(&self->view);
514514
}
515515

516+
/* Alternate version of memory_subcript that only accepts indices.
517+
Used by PySeqIter_New().
518+
*/
519+
static PyObject *
520+
memory_item(PyMemoryViewObject *self, Py_ssize_t result)
521+
{
522+
Py_buffer *view = &(self->view);
523+
524+
if (view->ndim == 0) {
525+
PyErr_SetString(PyExc_IndexError,
526+
"invalid indexing of 0-dim memory");
527+
return NULL;
528+
}
529+
if (view->ndim == 1) {
530+
/* Return a bytes object */
531+
char *ptr;
532+
ptr = (char *)view->buf;
533+
if (result < 0) {
534+
result += get_shape0(view);
535+
}
536+
if ((result < 0) || (result >= get_shape0(view))) {
537+
PyErr_SetString(PyExc_IndexError,
538+
"index out of bounds");
539+
return NULL;
540+
}
541+
if (view->strides == NULL)
542+
ptr += view->itemsize * result;
543+
else
544+
ptr += view->strides[0] * result;
545+
if (view->suboffsets != NULL &&
546+
view->suboffsets[0] >= 0) {
547+
ptr = *((char **)ptr) + view->suboffsets[0];
548+
}
549+
return PyBytes_FromStringAndSize(ptr, view->itemsize);
550+
} else {
551+
/* Return a new memory-view object */
552+
Py_buffer newview;
553+
memset(&newview, 0, sizeof(newview));
554+
/* XXX: This needs to be fixed so it actually returns a sub-view */
555+
return PyMemoryView_FromBuffer(&newview);
556+
}
557+
}
558+
516559
/*
517560
mem[obj] returns a bytes object holding the data for one element if
518561
obj fully indexes the memory view or another memory-view object
@@ -544,37 +587,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
544587
result = PyNumber_AsSsize_t(key, NULL);
545588
if (result == -1 && PyErr_Occurred())
546589
return NULL;
547-
if (view->ndim == 1) {
548-
/* Return a bytes object */
549-
char *ptr;
550-
ptr = (char *)view->buf;
551-
if (result < 0) {
552-
result += get_shape0(view);
553-
}
554-
if ((result < 0) || (result >= get_shape0(view))) {
555-
PyErr_SetString(PyExc_IndexError,
556-
"index out of bounds");
557-
return NULL;
558-
}
559-
if (view->strides == NULL)
560-
ptr += view->itemsize * result;
561-
else
562-
ptr += view->strides[0] * result;
563-
if (view->suboffsets != NULL &&
564-
view->suboffsets[0] >= 0) {
565-
ptr = *((char **)ptr) + view->suboffsets[0];
566-
}
567-
return PyBytes_FromStringAndSize(ptr, view->itemsize);
568-
}
569-
else {
570-
/* Return a new memory-view object */
571-
Py_buffer newview;
572-
memset(&newview, 0, sizeof(newview));
573-
/* XXX: This needs to be fixed so it
574-
actually returns a sub-view
575-
*/
576-
return PyMemoryView_FromBuffer(&newview);
577-
}
590+
return memory_item(self, result);
578591
}
579592
else if (PySlice_Check(key)) {
580593
Py_ssize_t start, stop, step, slicelength;
@@ -779,6 +792,12 @@ static PyMappingMethods memory_as_mapping = {
779792
(objobjargproc)memory_ass_sub, /* mp_ass_subscript */
780793
};
781794

795+
static PySequenceMethods memory_as_sequence = {
796+
0, /* sq_length */
797+
0, /* sq_concat */
798+
0, /* sq_repeat */
799+
(ssizeargfunc)memory_item, /* sq_item */
800+
};
782801

783802
/* Buffer methods */
784803
static PyBufferProcs memory_as_buffer = {
@@ -803,7 +822,7 @@ PyTypeObject PyMemoryView_Type = {
803822
0, /* tp_compare */
804823
(reprfunc)memory_repr, /* tp_repr */
805824
0, /* tp_as_number */
806-
0, /* tp_as_sequence */
825+
&memory_as_sequence, /* tp_as_sequence */
807826
&memory_as_mapping, /* tp_as_mapping */
808827
0, /* tp_hash */
809828
0, /* tp_call */

0 commit comments

Comments
 (0)