https://github.com/python/cpython/commit/85f89cb3e6bea6022cb58ffda560cf435f0adf94
commit: 85f89cb3e6bea6022cb58ffda560cf435f0adf94
branch: main
author: Sergey B Kirpichev <skirpic...@gmail.com>
committer: vstinner <vstin...@python.org>
date: 2025-04-23T15:38:24+02:00
summary:

gh-121249: adjust formatting codes for complex types in struct/ctypes (#132827)

* F - for float _Complex
* D - for double _Complex
* G - for long double _Complex (not supported by the struct module)

files:
M Doc/library/struct.rst
M Doc/whatsnew/3.14.rst
M Lib/ctypes/__init__.py
M Lib/test/test_ctypes/test_c_simple_type_meta.py
M Lib/test/test_struct.py
M Modules/_ctypes/callproc.c
M Modules/_ctypes/cfield.c
M Modules/_struct.c

diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst
index 3ea9e5ba071289..071b90b9359fa5 100644
--- a/Doc/library/struct.rst
+++ b/Doc/library/struct.rst
@@ -273,9 +273,9 @@ C11 standard) is supported, the following format characters 
are available:
 
+--------+--------------------------+--------------------+----------------+------------+
 | Format | C Type                   | Python type        | Standard size  | 
Notes      |
 
+========+==========================+====================+================+============+
-| ``E``  | :c:expr:`float complex`  | complex            | 8              | 
\(10)      |
+| ``F``  | :c:expr:`float complex`  | complex            | 8              | 
\(10)      |
 
+--------+--------------------------+--------------------+----------------+------------+
-| ``C``  | :c:expr:`double complex` | complex            | 16             | 
\(10)      |
+| ``D``  | :c:expr:`double complex` | complex            | 16             | 
\(10)      |
 
+--------+--------------------------+--------------------+----------------+------------+
 
 .. versionchanged:: 3.3
@@ -285,7 +285,7 @@ C11 standard) is supported, the following format characters 
are available:
    Added support for the ``'e'`` format.
 
 .. versionchanged:: 3.14
-   Added support for the ``'E'`` and ``'C'`` formats.
+   Added support for the ``'F'`` and ``'D'`` formats.
 
 
 Notes:
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 0f73b0e73195ee..5b03bd9e5a8caf 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -1173,7 +1173,7 @@ struct
 ------
 
 * Support the :c:expr:`float complex` and :c:expr:`double complex` C types in
-  the :mod:`struct` module (formatting characters ``'E'`` and ``'C'``,
+  the :mod:`struct` module (formatting characters ``'F'`` and ``'D'``,
   respectively) if the compiler has C11 complex arithmetic.
   (Contributed by Sergey B Kirpichev in :gh:`121249`.)
 
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py
index bba08b99b95b8b..b0e74f679ed18a 100644
--- a/Lib/ctypes/__init__.py
+++ b/Lib/ctypes/__init__.py
@@ -209,13 +209,13 @@ class c_longdouble(_SimpleCData):
 
 try:
     class c_double_complex(_SimpleCData):
-        _type_ = "C"
+        _type_ = "D"
     _check_size(c_double_complex)
     class c_float_complex(_SimpleCData):
-        _type_ = "E"
+        _type_ = "F"
     _check_size(c_float_complex)
     class c_longdouble_complex(_SimpleCData):
-        _type_ = "F"
+        _type_ = "G"
 except AttributeError:
     pass
 
diff --git a/Lib/test/test_ctypes/test_c_simple_type_meta.py 
b/Lib/test/test_ctypes/test_c_simple_type_meta.py
index b446fd5c77dde2..2328611856a1a0 100644
--- a/Lib/test/test_ctypes/test_c_simple_type_meta.py
+++ b/Lib/test/test_ctypes/test_c_simple_type_meta.py
@@ -160,11 +160,11 @@ def test_bad_type_message(self):
             class F(metaclass=PyCSimpleType):
                 _type_ = "\0"
         message = str(cm.exception)
-        expected_type_chars = list('cbBhHiIlLdCEFfuzZqQPXOv?g')
+        expected_type_chars = list('cbBhHiIlLdDFGfuzZqQPXOv?g')
         if not hasattr(ctypes, 'c_float_complex'):
-            expected_type_chars.remove('C')
-            expected_type_chars.remove('E')
             expected_type_chars.remove('F')
+            expected_type_chars.remove('D')
+            expected_type_chars.remove('G')
         if not MS_WINDOWS:
             expected_type_chars.remove('X')
         self.assertIn("'" + ''.join(expected_type_chars) + "'", message)
diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py
index b99391e482ff70..a410fd5a1940d1 100644
--- a/Lib/test/test_struct.py
+++ b/Lib/test/test_struct.py
@@ -23,7 +23,7 @@
 NAN = float('nan')
 
 try:
-    struct.pack('C', 1j)
+    struct.pack('D', 1j)
     have_c_complex = True
 except struct.error:
     have_c_complex = False
@@ -801,23 +801,23 @@ def test_c_complex_round_trip(self):
         values = [complex(*_) for _ in combinations([1, -1, 0.0, -0.0, 2,
                                                      -3, INF, -INF, NAN], 2)]
         for z in values:
-            for f in ['E', 'C', '>E', '>C', '<E', '<C']:
+            for f in ['F', 'D', '>F', '>D', '<F', '<D']:
                 with self.subTest(z=z, format=f):
                     round_trip = struct.unpack(f, struct.pack(f, z))[0]
                     self.assertComplexesAreIdentical(z, round_trip)
 
     @unittest.skipIf(have_c_complex, "requires no C11 complex type support")
     def test_c_complex_error(self):
-        msg1 = "'E' format not supported on this system"
-        msg2 = "'C' format not supported on this system"
+        msg1 = "'F' format not supported on this system"
+        msg2 = "'D' format not supported on this system"
         with self.assertRaisesRegex(struct.error, msg1):
-            struct.pack('E', 1j)
+            struct.pack('F', 1j)
         with self.assertRaisesRegex(struct.error, msg1):
-            struct.unpack('E', b'1')
+            struct.unpack('F', b'1')
         with self.assertRaisesRegex(struct.error, msg2):
-            struct.pack('C', 1j)
+            struct.pack('D', 1j)
         with self.assertRaisesRegex(struct.error, msg2):
-            struct.unpack('C', b'1')
+            struct.unpack('D', b'1')
 
 
 class UnpackIteratorTest(unittest.TestCase):
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index 36b5a7556f3888..83471aa3a42ad2 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -648,14 +648,14 @@ union result {
     int i;
     long l;
     long long q;
-    long double D;
+    long double g;
     double d;
     float f;
     void *p;
 #if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
-    double complex C;
-    float complex E;
-    long double complex F;
+    double complex D;
+    float complex F;
+    long double complex G;
 #endif
 };
 
diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c
index 6b63a08ed6eaa1..580ea18af2a43a 100644
--- a/Modules/_ctypes/cfield.c
+++ b/Modules/_ctypes/cfield.c
@@ -764,9 +764,9 @@ d_get(void *ptr, Py_ssize_t size)
 }
 
 #if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
-/* C: double complex */
+/* D: double complex */
 static PyObject *
-C_set(void *ptr, PyObject *value, Py_ssize_t size)
+D_set(void *ptr, PyObject *value, Py_ssize_t size)
 {
     assert(NUM_BITS(size) || (size == sizeof(double complex)));
     Py_complex c = PyComplex_AsCComplex(value);
@@ -780,7 +780,7 @@ C_set(void *ptr, PyObject *value, Py_ssize_t size)
 }
 
 static PyObject *
-C_get(void *ptr, Py_ssize_t size)
+D_get(void *ptr, Py_ssize_t size)
 {
     assert(NUM_BITS(size) || (size == sizeof(double complex)));
     double complex x;
@@ -789,9 +789,9 @@ C_get(void *ptr, Py_ssize_t size)
     return PyComplex_FromDoubles(creal(x), cimag(x));
 }
 
-/* E: float complex */
+/* F: float complex */
 static PyObject *
-E_set(void *ptr, PyObject *value, Py_ssize_t size)
+F_set(void *ptr, PyObject *value, Py_ssize_t size)
 {
     assert(NUM_BITS(size) || (size == sizeof(float complex)));
     Py_complex c = PyComplex_AsCComplex(value);
@@ -805,7 +805,7 @@ E_set(void *ptr, PyObject *value, Py_ssize_t size)
 }
 
 static PyObject *
-E_get(void *ptr, Py_ssize_t size)
+F_get(void *ptr, Py_ssize_t size)
 {
     assert(NUM_BITS(size) || (size == sizeof(float complex)));
     float complex x;
@@ -814,9 +814,9 @@ E_get(void *ptr, Py_ssize_t size)
     return PyComplex_FromDoubles(crealf(x), cimagf(x));
 }
 
-/* F: long double complex */
+/* G: long double complex */
 static PyObject *
-F_set(void *ptr, PyObject *value, Py_ssize_t size)
+G_set(void *ptr, PyObject *value, Py_ssize_t size)
 {
     assert(NUM_BITS(size) || (size == sizeof(long double complex)));
     Py_complex c = PyComplex_AsCComplex(value);
@@ -830,7 +830,7 @@ F_set(void *ptr, PyObject *value, Py_ssize_t size)
 }
 
 static PyObject *
-F_get(void *ptr, Py_ssize_t size)
+G_get(void *ptr, Py_ssize_t size)
 {
     assert(NUM_BITS(size) || (size == sizeof(long double complex)));
     long double complex x;
@@ -1372,7 +1372,7 @@ struct formattable {
 for nbytes in 8, 16, 32, 64:
     for sgn in 'i', 'u':
         print(f'    struct fielddesc fmt_{sgn}{nbytes};')
-for code in 'sbBcdCEFgfhHiIlLqQPzuUZXvO':
+for code in 'sbBcdFDGgfhHiIlLqQPzuUZXvO':
     print(f'    struct fielddesc fmt_{code};')
 [python start generated code]*/
     struct fielddesc fmt_i8;
@@ -1388,9 +1388,9 @@ for code in 'sbBcdCEFgfhHiIlLqQPzuUZXvO':
     struct fielddesc fmt_B;
     struct fielddesc fmt_c;
     struct fielddesc fmt_d;
-    struct fielddesc fmt_C;
-    struct fielddesc fmt_E;
     struct fielddesc fmt_F;
+    struct fielddesc fmt_D;
+    struct fielddesc fmt_G;
     struct fielddesc fmt_g;
     struct fielddesc fmt_f;
     struct fielddesc fmt_h;
@@ -1409,7 +1409,7 @@ for code in 'sbBcdCEFgfhHiIlLqQPzuUZXvO':
     struct fielddesc fmt_X;
     struct fielddesc fmt_v;
     struct fielddesc fmt_O;
-/*[python end generated code: output=fa648744ec7f919d input=087d58357d4bf2c5]*/
+/*[python end generated code: output=f5a07c066fedaca6 input=ffa5d46c29dfb07a]*/
 
     // bool has code '?':
     struct fielddesc fmt_bool;
@@ -1598,9 +1598,9 @@ for base_code, base_c_type in [
     TABLE_ENTRY_SW(d, &ffi_type_double);
 #if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
     if (Py_FFI_COMPLEX_AVAILABLE) {
-        TABLE_ENTRY(C, &ffi_type_complex_double);
-        TABLE_ENTRY(E, &ffi_type_complex_float);
-        TABLE_ENTRY(F, &ffi_type_complex_longdouble);
+        TABLE_ENTRY(D, &ffi_type_complex_double);
+        TABLE_ENTRY(F, &ffi_type_complex_float);
+        TABLE_ENTRY(G, &ffi_type_complex_longdouble);
     }
 #endif
     TABLE_ENTRY(g, &ffi_type_longdouble);
@@ -1635,7 +1635,7 @@ for base_code, base_c_type in [
     formattable.fmt_bool.getfunc = bool_get;
 
 /*[python input]
-all_chars = "cbBhHiIlLdCEFfuzZqQPXOv?g"
+all_chars = "cbBhHiIlLdDFGfuzZqQPXOv?g"
 print(f'    assert(sizeof(formattable.simple_type_chars) == 
{len(all_chars)+1});')
 print(f'    int i = 0;')
 for char in all_chars:
@@ -1656,9 +1656,9 @@ print(f"    formattable.simple_type_chars[i] = 0;")
     if (formattable.fmt_l.code) formattable.simple_type_chars[i++] = 'l';
     if (formattable.fmt_L.code) formattable.simple_type_chars[i++] = 'L';
     if (formattable.fmt_d.code) formattable.simple_type_chars[i++] = 'd';
-    if (formattable.fmt_C.code) formattable.simple_type_chars[i++] = 'C';
-    if (formattable.fmt_E.code) formattable.simple_type_chars[i++] = 'E';
+    if (formattable.fmt_D.code) formattable.simple_type_chars[i++] = 'D';
     if (formattable.fmt_F.code) formattable.simple_type_chars[i++] = 'F';
+    if (formattable.fmt_G.code) formattable.simple_type_chars[i++] = 'G';
     if (formattable.fmt_f.code) formattable.simple_type_chars[i++] = 'f';
     if (formattable.fmt_u.code) formattable.simple_type_chars[i++] = 'u';
     if (formattable.fmt_z.code) formattable.simple_type_chars[i++] = 'z';
@@ -1672,7 +1672,7 @@ print(f"    formattable.simple_type_chars[i] = 0;")
     if (formattable.fmt_bool.code) formattable.simple_type_chars[i++] = '?';
     if (formattable.fmt_g.code) formattable.simple_type_chars[i++] = 'g';
     formattable.simple_type_chars[i] = 0;
-/*[python end generated code: output=e6e5098a02f4b606 input=72031a625eac00c1]*/
+/*[python end generated code: output=2aa52670d1570f18 input=cff3e7cb95adac61]*/
 
 }
 #undef FIXINT_FIELDDESC_FOR
@@ -1689,7 +1689,7 @@ _ctypes_get_fielddesc(const char *fmt)
     struct fielddesc *result = NULL;
     switch(fmt[0]) {
 /*[python input]
-for code in 'sbBcdCEFgfhHiIlLqQPzuUZXvO':
+for code in 'sbBcdDFGgfhHiIlLqQPzuUZXvO':
     print(f"        case '{code}': result = &formattable.fmt_{code}; break;")
 [python start generated code]*/
         case 's': result = &formattable.fmt_s; break;
@@ -1697,9 +1697,9 @@ for code in 'sbBcdCEFgfhHiIlLqQPzuUZXvO':
         case 'B': result = &formattable.fmt_B; break;
         case 'c': result = &formattable.fmt_c; break;
         case 'd': result = &formattable.fmt_d; break;
-        case 'C': result = &formattable.fmt_C; break;
-        case 'E': result = &formattable.fmt_E; break;
+        case 'D': result = &formattable.fmt_D; break;
         case 'F': result = &formattable.fmt_F; break;
+        case 'G': result = &formattable.fmt_G; break;
         case 'g': result = &formattable.fmt_g; break;
         case 'f': result = &formattable.fmt_f; break;
         case 'h': result = &formattable.fmt_h; break;
@@ -1718,7 +1718,7 @@ for code in 'sbBcdCEFgfhHiIlLqQPzuUZXvO':
         case 'X': result = &formattable.fmt_X; break;
         case 'v': result = &formattable.fmt_v; break;
         case 'O': result = &formattable.fmt_O; break;
-/*[python end generated code: output=81a8223dda9f81f7 input=2f59666d3c024edf]*/
+/*[python end generated code: output=6e5c91940732fde9 input=902223feffc2fe38]*/
         case '?': result = &formattable.fmt_bool; break;
     }
     if (!result || !result->code) {
diff --git a/Modules/_struct.c b/Modules/_struct.c
index f04805d9d6d1d7..9910986a39570f 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -913,11 +913,11 @@ static const formatdef native_table[] = {
     {'f',       sizeof(float),  FLOAT_ALIGN,    nu_float,       np_float},
     {'d',       sizeof(double), DOUBLE_ALIGN,   nu_double,      np_double},
 #ifdef Py_HAVE_C_COMPLEX
-    {'E',       sizeof(float complex), FLOAT_COMPLEX_ALIGN, nu_float_complex, 
np_float_complex},
-    {'C',       sizeof(double complex), DOUBLE_COMPLEX_ALIGN, 
nu_double_complex, np_double_complex},
+    {'F',       sizeof(float complex), FLOAT_COMPLEX_ALIGN, nu_float_complex, 
np_float_complex},
+    {'D',       sizeof(double complex), DOUBLE_COMPLEX_ALIGN, 
nu_double_complex, np_double_complex},
 #else
-    {'E',       1, 0, nu_complex_stub, np_complex_stub},
-    {'C',       1, 0, nu_complex_stub, np_complex_stub},
+    {'F',       1, 0, nu_complex_stub, np_complex_stub},
+    {'D',       1, 0, nu_complex_stub, np_complex_stub},
 #endif
     {'P',       sizeof(void *), VOID_P_ALIGN,   nu_void_p,      np_void_p},
     {0}
@@ -1253,11 +1253,11 @@ static formatdef bigendian_table[] = {
     {'f',       4,              0,              bu_float,       bp_float},
     {'d',       8,              0,              bu_double,      bp_double},
 #ifdef Py_HAVE_C_COMPLEX
-    {'E',       8,              0,              bu_float_complex, 
bp_float_complex},
-    {'C',       16,             0,              bu_double_complex, 
bp_double_complex},
+    {'F',       8,              0,              bu_float_complex, 
bp_float_complex},
+    {'D',       16,             0,              bu_double_complex, 
bp_double_complex},
 #else
-    {'E',       1,              0,              nu_complex_stub, 
np_complex_stub},
-    {'C',       1,              0,              nu_complex_stub, 
np_complex_stub},
+    {'F',       1,              0,              nu_complex_stub, 
np_complex_stub},
+    {'D',       1,              0,              nu_complex_stub, 
np_complex_stub},
 #endif
     {0}
 };
@@ -1577,11 +1577,11 @@ static formatdef lilendian_table[] = {
     {'f',       4,              0,              lu_float,       lp_float},
     {'d',       8,              0,              lu_double,      lp_double},
 #ifdef Py_HAVE_C_COMPLEX
-    {'E',       8,              0,              lu_float_complex, 
lp_float_complex},
-    {'C',       16,             0,              lu_double_complex, 
lp_double_complex},
+    {'F',       8,              0,              lu_float_complex, 
lp_float_complex},
+    {'D',       16,             0,              lu_double_complex, 
lp_double_complex},
 #else
-    {'E',       1,              0,              nu_complex_stub, 
np_complex_stub},
-    {'C',       1,              0,              nu_complex_stub, 
np_complex_stub},
+    {'F',       1,              0,              nu_complex_stub, 
np_complex_stub},
+    {'D',       1,              0,              nu_complex_stub, 
np_complex_stub},
 #endif
     {0}
 };

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to