https://github.com/python/cpython/commit/5dd5c8b5a66af18904d4e015ce3120e2686ddb23
commit: 5dd5c8b5a66af18904d4e015ce3120e2686ddb23
branch: main
author: Victor Stinner <[email protected]>
committer: encukou <[email protected]>
date: 2026-05-04T17:26:30+02:00
summary:

gh-148675: Remove F and D formats from array and memoryview (GH-149368)

files:
A Misc/NEWS.d/next/Library/2026-05-04-16-26-33.gh-issue-148675.xZwXa6.rst
M Doc/library/array.rst
M Doc/whatsnew/3.15.rst
M Lib/test/test_array.py
M Lib/test/test_buffer.py
M Lib/test/test_memoryview.py
M Modules/arraymodule.c
M Objects/memoryobject.c

diff --git a/Doc/library/array.rst b/Doc/library/array.rst
index 3cd107460596d1..02eb775f31effc 100644
--- a/Doc/library/array.rst
+++ b/Doc/library/array.rst
@@ -48,10 +48,6 @@ defined:
 
+-----------+--------------------+-------------------+-----------------------+-------+
 | ``'d'``   | double             | float             | 8                     | 
      |
 
+-----------+--------------------+-------------------+-----------------------+-------+
-| ``'F'``   | float complex      | complex           | 8                     | 
\(4)  |
-+-----------+--------------------+-------------------+-----------------------+-------+
-| ``'D'``   | double complex     | complex           | 16                    | 
\(4)  |
-+-----------+--------------------+-------------------+-----------------------+-------+
 | ``'Zf'``  | float complex      | complex           | 8                     | 
\(4)  |
 
+-----------+--------------------+-------------------+-----------------------+-------+
 | ``'Zd'``  | double complex     | complex           | 16                    | 
\(4)  |
@@ -84,7 +80,7 @@ Notes:
    .. versionadded:: 3.15
 
 (4)
-   Complex types (``F``, ``D``, ``Zf`` and ``Zd``) are available 
unconditionally,
+   Complex types (``Zf`` and ``Zd``) are available unconditionally,
    regardless on support for complex types (the Annex G of the C11 standard)
    by the C compiler.
    As specified in the C11 standard, each complex type is represented by a
diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index 2e408f258e2805..29576d15b3b181 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -671,8 +671,8 @@ Other language changes
   (Contributed by James Hilton-Balfe in :gh:`128335`.)
 
 * The class :class:`memoryview` now supports the :c:expr:`float complex` and
-  :c:expr:`double complex` C types: formatting characters ``'F'``/``'Zf'``
-  and ``'D'``/``'Zd'`` respectively.
+  :c:expr:`double complex` C types: formatting characters ``'Zf'`` and ``'Zd'``
+  respectively.
   (Contributed by Victor Stinner in :gh:`146151` and :gh:`148675`.)
 
 * Allow the *count* argument of :meth:`bytes.replace` to be a keyword.
@@ -724,7 +724,7 @@ array
 -----
 
 * Support the :c:expr:`float complex` and :c:expr:`double complex` C types:
-  formatting characters ``'F'``/``'Zf'`` and ``'D'``/``'Zd'`` respectively.
+  formatting characters ``'Zf'`` and ``'Zd'`` respectively.
   (Contributed by Victor Stinner in :gh:`146151` and :gh:`148675`.)
 
 * Support half-floats (16-bit IEEE 754 binary interchange format): formatting
diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py
index 54ecc886917dc7..f7fa56a6e4bfa0 100755
--- a/Lib/test/test_array.py
+++ b/Lib/test/test_array.py
@@ -33,7 +33,7 @@ def __init__(self, typecode, newarg=None):
 
 typecodes = (
     'u', 'w', 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L',
-    'f', 'd', 'q', 'Q', 'F', 'D', 'e', 'Zf', 'Zd')
+    'f', 'd', 'q', 'Q', 'e', 'Zf', 'Zd')
 
 
 class MiscTest(unittest.TestCase):
@@ -210,14 +210,6 @@ def test_numbers(self):
              [9006104071832581.0, float('inf'), float('-inf'), -0.0]),
             (['d'], IEEE_754_DOUBLE_BE, '>dddd',
              [9006104071832581.0, float('inf'), float('-inf'), -0.0]),
-            (['F'], IEEE_754_FLOAT_COMPLEX_LE, '<FFFF',
-             [16711938.0j, float('inf'), complex('1-infj'), -0.0]),
-            (['F'], IEEE_754_FLOAT_COMPLEX_BE, '>FFFF',
-             [16711938.0j, float('inf'), complex('1-infj'), -0.0]),
-            (['D'], IEEE_754_DOUBLE_COMPLEX_LE, '<DDDD',
-             [9006104071832581.0j, float('inf'), complex('1-infj'), -0.0]),
-            (['D'], IEEE_754_DOUBLE_COMPLEX_BE, '>DDDD',
-             [9006104071832581.0j, float('inf'), complex('1-infj'), -0.0]),
             (['Zf'], IEEE_754_FLOAT_COMPLEX_LE, '<ZfZfZfZf',
              [16711938.0j, float('inf'), complex('1-infj'), -0.0]),
             (['Zf'], IEEE_754_FLOAT_COMPLEX_BE, '>ZfZfZfZf',
@@ -1645,18 +1637,10 @@ def test_alloc_overflow(self):
 
 
 class ComplexFloatTest(CFPTest, unittest.TestCase):
-    typecode = 'F'
-    minitemsize = 8
-
-class ComplexDoubleTest(CFPTest, unittest.TestCase):
-    typecode = 'D'
-    minitemsize = 16
-
-class ComplexZfFloatTest(CFPTest, unittest.TestCase):
     typecode = 'Zf'
     minitemsize = 8
 
-class ComplexZdDoubleTest(CFPTest, unittest.TestCase):
+class ComplexDoubleTest(CFPTest, unittest.TestCase):
     typecode = 'Zd'
     minitemsize = 16
 
diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py
index 21a3d0b3422ad2..f08faa14b24c64 100644
--- a/Lib/test/test_buffer.py
+++ b/Lib/test/test_buffer.py
@@ -67,7 +67,7 @@
     'h':0, 'H':0, 'i':0, 'I':0,
     'l':0, 'L':0, 'n':0, 'N':0,
     'e':0, 'f':0, 'd':0, 'P':0,
-    'F':0, 'D':0, 'Zf':0, 'Zd':0,
+    'Zf':0, 'Zd':0,
 }
 
 # NumPy does not have 'n' or 'N':
@@ -94,8 +94,6 @@
     'q':(-(1<<63), 1<<63), 'Q':(0, 1<<64),
     'e':(-65519, 65520),   'f':(-(1<<63), 1<<63),
     'd':(-(1<<1023), 1<<1023),
-    'F':(-(1<<63), 1<<63),
-    'D':(-(1<<1023), 1<<1023),
     'Zf':(-(1<<63), 1<<63),
     'Zd':(-(1<<1023), 1<<1023),
 }
@@ -112,9 +110,9 @@ def native_type_range(fmt):
         lh = (-(1<<63), 1<<63)
     elif fmt == 'd':
         lh = (-(1<<1023), 1<<1023)
-    elif fmt in ('F', 'Zf'):
+    elif fmt == 'Zf':
         lh = (-(1<<63), 1<<63)
-    elif fmt in ('D', 'Zd'):
+    elif fmt == 'Zd':
         lh = (-(1<<1023), 1<<1023)
     else:
         for exp in (128, 127, 64, 63, 32, 31, 16, 15, 8, 7):
@@ -184,7 +182,7 @@ def randrange_fmt(mode, char, obj):
     if char in 'efd':
         x = struct.pack(char, x)
         x = struct.unpack(char, x)[0]
-    if char in ('F', 'D', 'Zf', 'Zd'):
+    if char in ('Zf', 'Zd'):
         y = randrange(*fmtdict[mode][char])
         x = complex(x, y)
         x = struct.pack(char, x)
@@ -3055,7 +3053,7 @@ def test_memoryview_assign(self):
                 continue
             m2 = m1.cast(fmt)
             lo, hi = _range
-            if fmt in ("d", "f", "D", "F", "Zd", "Zf"):
+            if fmt in ("d", "f", "Zd", "Zf"):
                 lo, hi = -2**1024, 2**1024
             if fmt != 'P': # PyLong_AsVoidPtr() accepts negative numbers
                 self.assertRaises(ValueError, m2.__setitem__, 0, lo-1)
diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py
index f777ba583c5c06..f71b6f53486509 100644
--- a/Lib/test/test_memoryview.py
+++ b/Lib/test/test_memoryview.py
@@ -637,7 +637,7 @@ def check_equal(view, is_equal):
                 check_equal(m, True)
 
         # Test complex formats
-        for complex_format in ('F', 'D', 'Zf', 'Zd'):
+        for complex_format in ('Zf', 'Zd'):
             with self.subTest(format=complex_format):
                 data = struct.pack(complex_format * 3, 1.0, 2.0, float('nan'))
                 m = memoryview(data).cast(complex_format)
@@ -719,10 +719,6 @@ def test_half_float(self):
     def test_complex_types(self):
         float_complex_data = struct.pack('FFF', 0.0, -1.5j, 1+2j)
         double_complex_data = struct.pack('DDD', 0.0, -1.5j, 1+2j)
-        float_complex_view = memoryview(float_complex_data).cast('F')
-        double_complex_view = memoryview(double_complex_data).cast('D')
-        self.assertEqual(float_complex_view.nbytes * 2, 
double_complex_view.nbytes)
-        self.assertListEqual(float_complex_view.tolist(), 
double_complex_view.tolist())
         float_complex_view = memoryview(float_complex_data).cast('Zf')
         double_complex_view = memoryview(double_complex_data).cast('Zd')
         self.assertEqual(float_complex_view.nbytes * 2, 
double_complex_view.nbytes)
diff --git 
a/Misc/NEWS.d/next/Library/2026-05-04-16-26-33.gh-issue-148675.xZwXa6.rst 
b/Misc/NEWS.d/next/Library/2026-05-04-16-26-33.gh-issue-148675.xZwXa6.rst
new file mode 100644
index 00000000000000..6ba2e7aabf9ec8
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-05-04-16-26-33.gh-issue-148675.xZwXa6.rst
@@ -0,0 +1,2 @@
+Remove ``F`` and ``D`` formats from :mod:`array` and :class:`memoryview`.
+Patch by Victor Stinner.
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 56a2a98fe42731..a8347123e6496a 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -782,8 +782,6 @@ static const struct arraydescr descriptors[] = {
     {"e", sizeof(short), e_getitem, e_setitem, NULL, 0, 0},
     {"f", sizeof(float), f_getitem, f_setitem, NULL, 0, 0},
     {"d", sizeof(double), d_getitem, d_setitem, NULL, 0, 0},
-    {"F", 2*sizeof(float), cf_getitem, cf_setitem, NULL, 0, 0},
-    {"D", 2*sizeof(double), cd_getitem, cd_setitem, NULL, 0, 0},
     {"Zf", 2*sizeof(float), cf_getitem, cf_setitem, NULL, 0, 0},
     {"Zd", 2*sizeof(double), cd_getitem, cd_setitem, NULL, 0, 0},
     {NULL, 0, 0, 0, 0, 0, 0} /* Sentinel */
@@ -1612,9 +1610,7 @@ array_array_byteswap_impl(arrayobject *self)
         }
         break;
     case 8:
-        if (strcmp(self->ob_descr->typecode, "F") != 0
-            && strcmp(self->ob_descr->typecode, "Zf") != 0)
-        {
+        if (strcmp(self->ob_descr->typecode, "Zf") != 0) {
             for (p = self->ob_item, i = Py_SIZE(self); --i >= 0; p += 8) {
                 char p0 = p[0];
                 char p1 = p[1];
@@ -1648,8 +1644,7 @@ array_array_byteswap_impl(arrayobject *self)
         }
         break;
     case 16:
-        assert(strcmp(self->ob_descr->typecode, "D") == 0
-               || strcmp(self->ob_descr->typecode, "Zd") == 0);
+        assert(strcmp(self->ob_descr->typecode, "Zd") == 0);
         for (p = self->ob_item, i = Py_SIZE(self); --i >= 0; p += 8) {
             char t0 = p[0];
             char t1 = p[1];
@@ -2159,14 +2154,6 @@ typecode_to_mformat_code(const char *typecode)
     case 'd':
         return _PY_FLOAT_BIG_ENDIAN ? IEEE_754_DOUBLE_BE : IEEE_754_DOUBLE_LE;
 
-    case 'F':
-        return _PY_FLOAT_BIG_ENDIAN ? \
-            IEEE_754_FLOAT_COMPLEX_BE : IEEE_754_FLOAT_COMPLEX_LE;
-
-    case 'D':
-        return _PY_FLOAT_BIG_ENDIAN ? \
-            IEEE_754_DOUBLE_COMPLEX_BE : IEEE_754_DOUBLE_COMPLEX_LE;
-
     case 'Z': {
         switch (typecode[1]) {
         case 'f':
@@ -3167,7 +3154,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject 
*kwds)
     }
     Py_XDECREF(it);
     PyErr_SetString(PyExc_ValueError,
-        "bad typecode (must be b, B, u, w, h, H, i, I, l, L, q, Q, e, f, d, F, 
D, Zf or Zd)");
+        "bad typecode (must be b, B, u, w, h, H, i, I, l, L, q, Q, e, f, d, Zf 
or Zd)");
     return NULL;
 }
 
@@ -3205,8 +3192,6 @@ The following type codes are defined:\n\
     'e'         16-bit IEEE floats 2\n\
     'f'         floating-point     4\n\
     'd'         floating-point     8\n\
-    'F'         float complex      8\n\
-    'D'         double complex     16\n\
     'Zf'        float complex      8\n\
     'Zd'        double complex     16\n\
 \n\
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index 2c2f85ebf6acc0..900db864621a84 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -1217,8 +1217,6 @@ get_native_fmtchar(const char **result, const char *fmt)
     case 'f': size = sizeof(float); break;
     case 'd': size = sizeof(double); break;
     case 'e': size = sizeof(float) / 2; break;
-    case 'F': size = 2*sizeof(float); break;
-    case 'D': size = 2*sizeof(double); break;
     case '?': size = sizeof(_Bool); break;
     case 'P': size = sizeof(void *); break;
     case 'Z': {
@@ -1284,8 +1282,6 @@ get_native_fmtstr(const char *fmt)
     case 'f': RETURN("f");
     case 'd': RETURN("d");
     case 'e': RETURN("e");
-    case 'F': RETURN("F");
-    case 'D': RETURN("D");
     case 'Z': {
         switch (fmt[1]) {
         case 'f': RETURN("Zf");
@@ -1865,16 +1861,6 @@ unpack_single(PyMemoryViewObject *self, const char *ptr, 
const char *fmt)
     case 'e': d[0] = PyFloat_Unpack2(ptr, endian); goto convert_double;
 
     /* complexes */
-    case 'F':
-        d[0] = PyFloat_Unpack4(ptr, endian);
-        d[1] = PyFloat_Unpack4(ptr + sizeof(float), endian);
-        goto convert_double_complex;
-
-    case 'D':
-        d[0] = PyFloat_Unpack8(ptr, endian);
-        d[1] = PyFloat_Unpack8(ptr + sizeof(double), endian);
-        goto convert_double_complex;
-
     case 'Z': {
         switch (fmt[1]) {
         case 'f':
@@ -2055,24 +2041,6 @@ pack_single(PyMemoryViewObject *self, char *ptr, 
PyObject *item, const char *fmt
         break;
 
     /* complexes */
-    case 'F': case 'D':
-        c = PyComplex_AsCComplex(item);
-        if (c.real == -1.0 && PyErr_Occurred()) {
-            goto err_occurred;
-        }
-        CHECK_RELEASED_INT_AGAIN(self);
-        if (fmt[0] == 'D') {
-            double x[2] = {c.real, c.imag};
-
-            memcpy(ptr, &x, sizeof(x));
-        }
-        else {
-            float x[2] = {(float)c.real, (float)c.imag};
-
-            memcpy(ptr, &x, sizeof(x));
-        }
-        break;
-
     case 'Z': {
         switch (fmt[1]) {
         case 'f': case 'd':
@@ -3138,22 +3106,6 @@ unpack_cmp(const char *p, const char *q, const char *fmt,
     }
 
     /* complexes */
-    case 'F':
-    {
-         float x[2], y[2];
-
-         memcpy(&x, p, sizeof(x));
-         memcpy(&y, q, sizeof(y));
-         return (x[0] == y[0]) && (x[1] == y[1]);
-    }
-    case 'D':
-    {
-         double x[2], y[2];
-
-         memcpy(&x, p, sizeof(x));
-         memcpy(&y, q, sizeof(y));
-         return (x[0] == y[0]) && (x[1] == y[1]);
-    }
     case 'Z': {
         switch (fmt[1]) {
         case 'f':

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to