]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-91484: Allow memoryview cast for F-contiguous (GH-137803)
authorJaemin Park <56078563+jamie2779@users.noreply.github.com>
Fri, 24 Jul 2026 13:17:06 +0000 (22:17 +0900)
committerGitHub <noreply@github.com>
Fri, 24 Jul 2026 13:17:06 +0000 (13:17 +0000)
Doc/library/stdtypes.rst
Doc/whatsnew/3.16.rst
Lib/test/test_buffer.py
Misc/NEWS.d/next/Core_and_Builtins/2025-08-15-06-28-45.gh-issue-91484.huCgHt.rst [new file with mode: 0644]
Objects/memoryobject.c

index 9df5eb78d286a52ea001e498dfdb7e9fbc202eed..0b6a1b488fb64f9ea6d2e47c5ecbc57db4e3c2a5 100644 (file)
@@ -4876,8 +4876,9 @@ copying.
       Cast a memoryview to a new format or shape. *shape* defaults to
       ``[byte_length//new_itemsize]``, which means that the result view
       will be one-dimensional. The return value is a new memoryview, but
-      the buffer itself is not copied. Supported casts are 1D -> C-:term:`contiguous`
-      and C-contiguous -> 1D.
+      the buffer itself is not copied. Supported casts are
+      1D -> C-:term:`contiguous`, C-contiguous -> 1D, and
+      F-contiguous -> 1D.
 
       The destination format is restricted to a single element native format in
       :mod:`struct` syntax. One of the formats must be a byte format
@@ -4964,6 +4965,10 @@ copying.
       .. versionchanged:: 3.5
          The source format is no longer restricted when casting to a byte view.
 
+      .. versionchanged:: next
+         Casting a multi-dimensional F-contiguous view to a one-dimensional
+         view is now supported.
+
    .. method:: count(value, /)
 
       Count the number of occurrences of *value*.
index 662defa709a246c8fd731f9a3b07180598a4096d..06e831ea1e34631d5221938fc76b7cfd7d24cb9d 100644 (file)
@@ -75,6 +75,10 @@ New features
 Other language changes
 ======================
 
+* :meth:`memoryview.cast` now allows casting a multidimensional
+  F-contiguous view to a one-dimensional view.
+  (Contributed by Jaemin Park in :gh:`91484`.)
+
 * :ref:`Frame objects <frame-objects>` now support :mod:`weak references
   <weakref>`.  This allows associating extra data with active frames,
   for example in debuggers, without keeping the frames (and everything
index 453dafe2709eb2fd356a855cc378c032058fea97..579e680448e94e30874643c1fbb30525a622b152 100644 (file)
@@ -2877,6 +2877,32 @@ class TestBufferProtocol(unittest.TestCase):
             self.assertEqual(m2.strides, (1,))
             self.assertEqual(m2.suboffsets, ())
 
+    def test_memoryview_cast_f_contiguous_ND_1D(self):
+        nd = ndarray(list(range(12)), shape=[3, 4], format='B', flags=ND_FORTRAN)
+        m = memoryview(nd)
+        self.assertTrue(m.f_contiguous)
+        self.assertTrue(m.contiguous)
+
+        m1 = m.cast('B')
+        self.assertEqual(m1.ndim, 1)
+        self.assertEqual(m1.shape, (m.nbytes,))
+        self.assertEqual(m1.strides, (1,))
+        self.assertTrue(m1.c_contiguous)
+        self.assertTrue(m1.contiguous)
+        self.assertEqual(m1.tobytes(), memoryview(nd).tobytes(order='F'))
+
+        for fmt in ('B', 'b', 'c', 'H', 'I'):
+            size = struct.calcsize(fmt)
+            if m.nbytes % size == 0:
+                m2 = m.cast(fmt)
+                self.assertEqual(m2.ndim, 1)
+                self.assertEqual(m2.shape, (m.nbytes // size,))
+                self.assertTrue(m2.contiguous)
+
+        m3 = m[::-1]
+        with self.assertRaises(TypeError):
+            m3.cast('B')
+
     def test_memoryview_tolist(self):
 
         # Most tolist() tests are in self.verify() etc.
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-08-15-06-28-45.gh-issue-91484.huCgHt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-08-15-06-28-45.gh-issue-91484.huCgHt.rst
new file mode 100644 (file)
index 0000000..7bba0da
--- /dev/null
@@ -0,0 +1 @@
+:meth:`memoryview.cast` now allows casting from N-D to 1-D for F-contiguous.
index d92c7daff15dbf3c83727c97cdcf100c004557c1..f6ffa337c632a0b630290ebe81ad874fbca5a45e 100644 (file)
@@ -1485,9 +1485,11 @@ memoryview_cast_impl(PyMemoryViewObject *self, PyObject *format,
     CHECK_RESTRICTED(self);
 
     if (!MV_C_CONTIGUOUS(self->flags)) {
-        PyErr_SetString(PyExc_TypeError,
-            "memoryview: casts are restricted to C-contiguous views");
-        return NULL;
+        if (shape || !MV_F_CONTIGUOUS(self->flags)) {
+            PyErr_SetString(PyExc_TypeError,
+                "memoryview: casts are restricted to contiguous views");
+            return NULL;
+        }
     }
     if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
         PyErr_SetString(PyExc_TypeError,