summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/stdtypes.rst15
-rw-r--r--Lib/test/test_buffer.py6
-rw-r--r--Lib/test/test_ctypes/test_pep3118.py24
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2020-02-11-15-54-40.bpo-39610.fvgsCl.rst2
-rw-r--r--Objects/memoryobject.c6
5 files changed, 31 insertions, 22 deletions
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
index aea2410..2360472 100644
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -3715,12 +3715,15 @@ copying.
types such as :class:`bytes` and :class:`bytearray`, an element is a single
byte, but other types such as :class:`array.array` may have bigger elements.
- ``len(view)`` is equal to the length of :class:`~memoryview.tolist`.
- If ``view.ndim = 0``, the length is 1. If ``view.ndim = 1``, the length
- is equal to the number of elements in the view. For higher dimensions,
- the length is equal to the length of the nested list representation of
- the view. The :class:`~memoryview.itemsize` attribute will give you the
- number of bytes in a single element.
+ ``len(view)`` is equal to the length of :class:`~memoryview.tolist`, which
+ is the nested list representation of the view. If ``view.ndim = 1``,
+ this is equal to the number of elements in the view.
+
+ .. versionchanged:: 3.12
+ If ``view.ndim == 0``, ``len(view)`` now raises :exc:`TypeError` instead of returning 1.
+
+ The :class:`~memoryview.itemsize` attribute will give you the number of
+ bytes in a single element.
A :class:`memoryview` supports slicing and indexing to expose its data.
One-dimensional slicing will result in a subview::
diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py
index 8ac3b7e..098d2d9 100644
--- a/Lib/test/test_buffer.py
+++ b/Lib/test/test_buffer.py
@@ -965,8 +965,10 @@ class TestBufferProtocol(unittest.TestCase):
self.assertEqual(m.strides, tuple(strides))
self.assertEqual(m.suboffsets, tuple(suboffsets))
- n = 1 if ndim == 0 else len(lst)
- self.assertEqual(len(m), n)
+ if ndim == 0:
+ self.assertRaises(TypeError, len, m)
+ else:
+ self.assertEqual(len(m), len(lst))
rep = result.tolist() if fmt else result.tobytes()
self.assertEqual(rep, lst)
diff --git a/Lib/test/test_ctypes/test_pep3118.py b/Lib/test/test_ctypes/test_pep3118.py
index c8a70e3..0381617 100644
--- a/Lib/test/test_ctypes/test_pep3118.py
+++ b/Lib/test/test_ctypes/test_pep3118.py
@@ -28,7 +28,7 @@ class Test(unittest.TestCase):
if shape:
self.assertEqual(len(v), shape[0])
else:
- self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob))
+ self.assertRaises(TypeError, len, v)
self.assertEqual(v.itemsize, sizeof(itemtp))
self.assertEqual(v.shape, shape)
# XXX Issue #12851: PyCData_NewGetBuffer() must provide strides
@@ -39,11 +39,10 @@ class Test(unittest.TestCase):
# they are always read/write
self.assertFalse(v.readonly)
- if v.shape:
- n = 1
- for dim in v.shape:
- n = n * dim
- self.assertEqual(n * v.itemsize, len(v.tobytes()))
+ n = 1
+ for dim in v.shape:
+ n = n * dim
+ self.assertEqual(n * v.itemsize, len(v.tobytes()))
except:
# so that we can see the failing type
print(tp)
@@ -58,7 +57,7 @@ class Test(unittest.TestCase):
if shape:
self.assertEqual(len(v), shape[0])
else:
- self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob))
+ self.assertRaises(TypeError, len, v)
self.assertEqual(v.itemsize, sizeof(itemtp))
self.assertEqual(v.shape, shape)
# XXX Issue #12851
@@ -67,11 +66,10 @@ class Test(unittest.TestCase):
# they are always read/write
self.assertFalse(v.readonly)
- if v.shape:
- n = 1
- for dim in v.shape:
- n = n * dim
- self.assertEqual(n, len(v))
+ n = 1
+ for dim in v.shape:
+ n = n * dim
+ self.assertEqual(n * v.itemsize, len(v.tobytes()))
except:
# so that we can see the failing type
print(tp)
@@ -243,7 +241,7 @@ class LEPoint(LittleEndianStructure):
#
endian_types = [
(BEPoint, "T{>l:x:>l:y:}".replace('l', s_long), (), BEPoint),
- (LEPoint, "T{<l:x:<l:y:}".replace('l', s_long), (), LEPoint),
+ (LEPoint * 1, "T{<l:x:<l:y:}".replace('l', s_long), (1,), LEPoint),
(POINTER(BEPoint), "&T{>l:x:>l:y:}".replace('l', s_long), (), POINTER(BEPoint)),
(POINTER(LEPoint), "&T{<l:x:<l:y:}".replace('l', s_long), (), POINTER(LEPoint)),
]
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-02-11-15-54-40.bpo-39610.fvgsCl.rst b/Misc/NEWS.d/next/Core and Builtins/2020-02-11-15-54-40.bpo-39610.fvgsCl.rst
new file mode 100644
index 0000000..d65e0f3
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-02-11-15-54-40.bpo-39610.fvgsCl.rst
@@ -0,0 +1,2 @@
+``len()`` for 0-dimensional :class:`memoryview`` objects (such as ``memoryview(ctypes.c_uint8(42))``) now raises a :exc:`TypeError`.
+Previously this returned ``1``, which was not consistent with ``mem_0d[0]`` raising an :exc:`IndexError``.
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index 1d6cc3b..34cc797 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -2642,7 +2642,11 @@ static Py_ssize_t
memory_length(PyMemoryViewObject *self)
{
CHECK_RELEASED_INT(self);
- return self->view.ndim == 0 ? 1 : self->view.shape[0];
+ if (self->view.ndim == 0) {
+ PyErr_SetString(PyExc_TypeError, "0-dim memory has no length");
+ return -1;
+ }
+ return self->view.shape[0];
}
/* As mapping */