Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-143715: deprecate incomplete initialization of struct.Struct()#143659

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
skirpichev wants to merge13 commits intopython:main
base:main
Choose a base branch
Loading
fromskirpichev:deprecate-struct-init-2/78724
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
13 commits
Select commitHold shift + click to select a range
fff147f
gh-78724: deprecate incomplete initialization of struct.Struct()
skirpichevJan 10, 2026
d2a0345
Merge branch 'master' into deprecate-struct-init-2/78724
skirpichevJan 12, 2026
589fbc7
address review: test_Struct_reinitialization()
skirpichevJan 12, 2026
5e91e87
catch new warning in test_operations_on_half_initialized_Struct()
skirpichevJan 12, 2026
babb274
add init_called flag
skirpichevJan 12, 2026
0e4e84b
Merge branch 'master' into deprecate-struct-init-2/78724
skirpichevJan 13, 2026
3f36635
a hack to support new idiom for subclassing
skirpichevJan 13, 2026
e576475
Merge branch 'master' into deprecate-struct-init-2/78724
skirpichevJan 17, 2026
628aadd
+ filter out Struct signature test
skirpichevJan 17, 2026
979cc18
Update Modules/_struct.c
skirpichevJan 19, 2026
f7492ec
Merge branch 'master' into deprecate-struct-init-2/78724
skirpichevJan 19, 2026
db8f5f2
address review: reformat s_new()
skirpichevJan 19, 2026
dc8cbef
address review: actual___init___impl -> s_init
skirpichevJan 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletionsDoc/deprecations/pending-removal-in-3.20.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
Pending removal in Python 3.20
------------------------------

* Calling the ``Struct.__new__()`` without required argument now is
deprecated and will be removed in Python 3.20. Calling
:meth:`~object.__init__` method on initialized :class:`~struct.Struct`
objects is deprecated and will be removed in Python 3.20.

(Contributed by Sergey B Kirpichev in :gh:`78724`.)

* The ``__version__``, ``version`` and ``VERSION`` attributes have been
deprecated in these standard library modules and will be removed in
Python 3.20. Use :py:data:`sys.version_info` instead.
Expand Down
9 changes: 9 additions & 0 deletionsDoc/whatsnew/3.15.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1167,6 +1167,15 @@ New deprecations

(Contributed by Bénédikt Tran in :gh:`134978`.)

* :mod:`struct`:

* Calling the ``Struct.__new__()`` without required argument now is
deprecated and will be removed in Python 3.20. Calling
:meth:`~object.__init__` method on initialized :class:`~struct.Struct`
objects is deprecated and will be removed in Python 3.20.

(Contributed by Sergey B Kirpichev in :gh:`78724`.)

* ``__version__``

* The ``__version__``, ``version`` and ``VERSION`` attributes have been
Expand Down
3 changes: 2 additions & 1 deletionLib/test/test_inspect/test_inspect.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -6268,7 +6268,8 @@ def test_stat_module_has_signatures(self):

def test_struct_module_has_signatures(self):
import struct
self._test_module_has_signatures(struct)
unsupported_signature = {'Struct'}
self._test_module_has_signatures(struct, unsupported_signature=unsupported_signature)

def test_string_module_has_signatures(self):
import string
Expand Down
15 changes: 11 additions & 4 deletionsLib/test/test_struct.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -582,11 +582,16 @@ def test_Struct_reinitialization(self):
# Struct instance. This test can be used to detect the leak
# when running with regrtest -L.
s = struct.Struct('i')
s.__init__('ii')
with self.assertWarns(DeprecationWarning):
s.__init__('ii')
self.assertEqual(s.format, 'ii')
packed = b'\x01\x00\x00\x00\x02\x00\x00\x00'
self.assertEqual(s.pack(1, 2), packed)
self.assertEqual(s.unpack(packed), (1, 2))

def check_sizeof(self, format_str, number_of_codes):
# The size of 'PyStructObject'
totalsize = support.calcobjsize('2n3P')
totalsize = support.calcobjsize('2n3P1?')
# The size taken up by the 'formatcode' dynamic array
totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1)
support.check_sizeof(self, struct.Struct(format_str), totalsize)
Expand DownExpand Up@@ -790,7 +795,8 @@ class MyStruct(struct.Struct):
def __init__(self):
super().__init__('>h')

my_struct = MyStruct()
with self.assertWarns(DeprecationWarning):
my_struct = MyStruct()
self.assertEqual(my_struct.pack(12345), b'\x30\x39')

def test_repr(self):
Expand DownExpand Up@@ -824,7 +830,8 @@ def test_endian_table_init_subinterpreters(self):
self.assertListEqual(list(results), [None] * 5)

def test_operations_on_half_initialized_Struct(self):
S = struct.Struct.__new__(struct.Struct)
with self.assertWarns(DeprecationWarning):
S = struct.Struct.__new__(struct.Struct)

spam = array.array('b', b' ')
self.assertRaises(RuntimeError, S.iter_unpack, spam)
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
Calling the ``Struct.__new__()`` without required argument now is deprecated.
Calling :meth:`~object.__init__` method on initialized :class:`~struct.Struct`
objects is deprecated. Patch by Sergey B Kirpichev.
101 changes: 67 additions & 34 deletionsModules/_struct.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -70,6 +70,7 @@ typedef struct {
formatcode *s_codes;
PyObject *s_format;
PyObject *weakreflist; /* List of weak references */
bool init_called;
} PyStructObject;

#define PyStructObject_CAST(op) ((PyStructObject *)(op))
Expand DownExpand Up@@ -1757,30 +1758,68 @@ prepare_s(PyStructObject *self)
return -1;
}

static int
s_init(PyStructObject *self, PyObject *format)
{
if (PyUnicode_Check(format)) {
format = PyUnicode_AsASCIIString(format);
if (format == NULL)
return -1;
}
else {
Py_INCREF(format);
}
if (!PyBytes_Check(format)) {
Py_DECREF(format);
PyErr_Format(PyExc_TypeError,
"Struct() argument 1 must be a str or bytes object, "
"not %T",
format);
return -1;
}
Py_SETREF(self->s_format, format);
if (prepare_s(self)) {
return -1;
}
return 0;
}

static PyObject *
s_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *self;
PyStructObject *self;

if ((PyTuple_GET_SIZE(args) != 1 || kwds)
&& PyErr_WarnEx(PyExc_DeprecationWarning,
"Struct.__new__() has one positional argument", 1))
{
return NULL;
}
assert(type != NULL);
allocfunc alloc_func = PyType_GetSlot(type, Py_tp_alloc);
assert(alloc_func != NULL);

self = alloc_func(type, 0);
if (self != NULL) {
PyStructObject *s = (PyStructObject*)self;
s->s_format = Py_NewRef(Py_None);
s->s_codes = NULL;
s->s_size = -1;
s->s_len = -1;
self = (PyStructObject *)alloc_func(type, 0);
if (self == NULL) {
return NULL;
}
self->s_format = Py_NewRef(Py_None);
self->s_codes = NULL;
self->s_size = -1;
self->s_len = -1;
self->init_called = false;
if (PyTuple_GET_SIZE(args) > 0) {
if (s_init(self, PyTuple_GET_ITEM(args, 0))) {
Py_DECREF(self);
return NULL;
}
}
return self;
return(PyObject *)self;
}

/*[clinic input]
Struct.__init__

format: object
format: object = NULL

Create a compiled struct object.

Expand All@@ -1790,32 +1829,28 @@ to the format string. See help(struct) for more on format strings.

static int
Struct___init___impl(PyStructObject *self, PyObject *format)
/*[clinic end generated code: output=b8e80862444e92d0 input=1af78a5f57d82cec]*/
/*[clinic end generated code: output=b8e80862444e92d0 input=6275ff3f85752dd7]*/
{
int ret = 0;

if (PyUnicode_Check(format)) {
format = PyUnicode_AsASCIIString(format);
if (format == NULL)
return -1;
if (!format && !self->s_codes) {
PyErr_SetString(PyExc_TypeError,
"Struct() missing required argument 'format' (pos 1)");
return -1;
}
else {
Py_INCREF(format);
if (!self->init_called) {
if (!self->s_codes && s_init(self, format)) {
return -1;
}
self->init_called = true;
return 0;
}

if (!PyBytes_Check(format)) {
Py_DECREF(format);
PyErr_Format(PyExc_TypeError,
"Struct() argument 1 must be a str or bytes object, "
"not %.200s",
_PyType_Name(Py_TYPE(format)));
if ((self->s_codes && self->init_called)
&& PyErr_WarnEx(PyExc_DeprecationWarning,
("Explicit call of __init__() on "
"initialized Struct() is deprecated"), 1))
{
return -1;
}

Py_SETREF(self->s_format, format);

ret = prepare_s(self);
return ret;
return s_init(self, format);
}

static int
Expand DownExpand Up@@ -2437,9 +2472,7 @@ static PyType_Slot PyStructType_slots[] = {
{Py_tp_members, s_members},
{Py_tp_getset, s_getsetlist},
{Py_tp_init, Struct___init__},
{Py_tp_alloc, PyType_GenericAlloc},
{Py_tp_new, s_new},
{Py_tp_free, PyObject_GC_Del},
{0, 0},
};

Expand Down
13 changes: 9 additions & 4 deletionsModules/clinic/_struct.c.h
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

Loading

[8]ページ先頭

©2009-2026 Movatter.jp