[issue4580] slicing of memoryviews when itemsize != 1 is wrong

Nick Coghlan report at bugs.python.org
Tue Dec 9 22:12:36 CET 2008


Nick Coghlan <ncoghlan at gmail.com> added the comment:

The patch still gets the length of memory view objects wrong - it just
makes it *consistently* wrong so that the specific assignment being
tested appears to work.

Note the following behaviour with the current memoryview :

>>> from array import array
>>> a10 = array('i', range(10))
>>> a6 = array('i', range(6))
>>> m10 = memoryview(a10)
>>> m6 = memoryview(a6)
>>> m = m10[2:8]
>>> len(m10)
40
>>> len(m6)
24
>>> len(m)
6

The patch will change the last item to 24 which will make the assignment
work, but it's still not the right answer!

As it turns out though, in addition to the length problems, this is far
from the only problem with memory view assignment - the damn things are
so finicky, it's practically impossible to assign anything to them:

>>> a = array('i', range(10))
>>> m = memoryview(a)
>>> m[1] = 1 # An integer perhaps?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' does not have the buffer interface
>>> m[1] = array('i', range(1)) # A single valued array?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: cannot modify size of memoryview object
>>> m[1] = b"1234" # A bytes object of the correct size?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: mismatching item sizes for "array.array" and "bytes"
>>> m[:1] = [0] # How about a sequence?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'list' does not have the buffer interface
>>> m[1] = memoryview(array('i', range(1)))[:1] # Force the returned
'len' to be wrong (but right for what memoryview is going to do with it)
and the assignment works

I guess fixing most of those qualify as enhancements though, as opposed
to the length calculation which is simply an outright bug.

So...

1. memoryview needs to be fixed so that internally self->view.len is
always the length in bytes, even after taking a slice of the view

2. memoryview needs to be fixed so that len() reflects the number of
items in the view (i.e. self->view.shape[0]), not the total number of bytes

3. array.array needs to be fixed so that it populates the shape array (a
pointer to the arrays own internal length field should be adequate)

4. PyObject_GetBuffer needs to raise an exception if it sees ndim > 0
with a NULL shape array in the resulting Py_buffer. The only time
shape=NULL is allowed is when ndim=0 (i.e. scalar values) because at
that point the length of the shape array is 0. The /* XXX */ comment in
the memoryview code about shape not being required by PEP 3118 needs to
go away because it *is* required - array.array is just broken in not
providing it.

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue4580>
_______________________________________


More information about the Python-bugs-list mailing list