Skip to content

Commit 9ca0a71

Browse files
committed
gh-121249: Deprecate using F/D type codes in the struct module
1 parent 49d484e commit 9ca0a71

5 files changed

Lines changed: 60 additions & 5 deletions

File tree

Doc/deprecations/pending-removal-in-3.21.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,9 @@ Pending removal in Python 3.21
1717
are not generated by the parser or accepted by the code generator.
1818
* The ``dims`` property of ``ast.Tuple`` will be removed in Python 3.21. Use
1919
the ``ast.Tuple.elts`` property instead.
20+
21+
* :mod:`struct`:
22+
23+
* Soft-deprecated since Python 3.15 using ``'F'`` and ``'D'`` type codes now
24+
deprecated. These codes will be removed in Python 3.21. Use instead
25+
two-letter forms ``'Zf'`` and ``'Zd'``.

Doc/whatsnew/3.16.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,13 @@ New deprecations
485485
3.9, now issues a deprecation warning on use. This property is slated for
486486
removal in 3.21. Use ``ast.Tuple.elts`` instead.
487487

488+
* :mod:`struct`:
489+
490+
* Soft-deprecated since Python 3.15 using ``'F'`` and ``'D'`` type codes now
491+
deprecated. These codes will be removed in Python 3.21. Use instead
492+
two-letter forms ``'Zf'`` and ``'Zd'``.
493+
(Contributed by Sergey B Kirpichev in :gh:`121249`.)
494+
488495
.. Add deprecations above alphabetically, not here at the end.
489496
490497
.. include:: ../deprecations/pending-removal-in-3.17.rst

Lib/test/test_struct.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import unittest
88
import struct
99
import sys
10+
import warnings
1011
import weakref
1112

1213
from test import support
@@ -995,14 +996,25 @@ def test_c_complex_round_trip(self):
995996
values = [complex(*_) for _ in combinations([1, -1, 0.0, -0.0, 2,
996997
-3, INF, -INF, NAN], 2)]
997998
for z in values:
998-
for f in [
999-
'F', 'D', 'Zf', 'Zd',
1000-
'>F', '>D', '>Zf', '>Zd',
1001-
'<F', '<D', '<Zf', '<Zd',
1002-
]:
999+
for f in ['Zf', 'Zd', '>Zf', '>Zd', '<Zf', '<Zd']:
10031000
with self.subTest(z=z, format=f):
10041001
round_trip = struct.unpack(f, struct.pack(f, z))[0]
10051002
self.assertComplexesAreIdentical(z, round_trip)
1003+
for f in ['F', 'D', '>F', '>D', '<F', '<D']:
1004+
z = 1+1j
1005+
with self.subTest(format=f):
1006+
with warnings.catch_warnings():
1007+
warnings.simplefilter("error", DeprecationWarning)
1008+
self.assertRaises(DeprecationWarning, struct.pack, f, z)
1009+
with warnings.catch_warnings():
1010+
with self.assertWarns(DeprecationWarning):
1011+
b = struct.pack(f, z)
1012+
with warnings.catch_warnings():
1013+
warnings.simplefilter("error", DeprecationWarning)
1014+
self.assertRaises(DeprecationWarning, struct.unpack, f, b)
1015+
with self.assertWarns(DeprecationWarning):
1016+
round_trip = struct.unpack(f, b)[0]
1017+
self.assertComplexesAreIdentical(z, round_trip)
10061018

10071019
@unittest.skipIf(
10081020
support.is_android or support.is_apple_mobile,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Deprecate using ``'F'`` and ``'D'`` type codes in the :mod:`struct`.

Modules/_struct.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,6 +1697,21 @@ prepare_s(PyStructObject *self, PyObject *format)
16971697
if (e == NULL)
16981698
return -1;
16991699

1700+
if (strcmp(e->format, "F") == 0) {
1701+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
1702+
"The 'F' type code is deprecated, use 'Zf'", 1))
1703+
{
1704+
return -1;
1705+
}
1706+
}
1707+
if (strcmp(e->format, "D") == 0) {
1708+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
1709+
"The 'D' type code is deprecated, use 'Zd'", 1))
1710+
{
1711+
return -1;
1712+
}
1713+
}
1714+
17001715
switch (c) {
17011716
case 's': _Py_FALLTHROUGH;
17021717
case 'p':
@@ -2065,6 +2080,20 @@ s_unpack_internal(PyStructObject *soself, const char *startfrom,
20652080
}
20662081
v = PyBytes_FromStringAndSize(res + 1, n);
20672082
} else {
2083+
if (strcmp(e->format, "F") == 0) {
2084+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
2085+
"The 'F' type code is deprecated, use 'Zf'", 1))
2086+
{
2087+
goto fail;
2088+
}
2089+
}
2090+
if (strcmp(e->format, "D") == 0) {
2091+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
2092+
"The 'D' type code is deprecated, use 'Zd'", 1))
2093+
{
2094+
goto fail;
2095+
}
2096+
}
20682097
v = e->unpack(state, res, e);
20692098
}
20702099
if (v == NULL)

0 commit comments

Comments
 (0)