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