Skip to content

Commit babb274

Browse files
committed
add init_called flag
1 parent 5e91e87 commit babb274

File tree

2 files changed

+53
-39
lines changed

2 files changed

+53
-39
lines changed

Lib/test/test_struct.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ def test_Struct_reinitialization(self):
584584

585585
def check_sizeof(self, format_str, number_of_codes):
586586
# The size of 'PyStructObject'
587-
totalsize = support.calcobjsize('2n3P')
587+
totalsize = support.calcobjsize('2n3P1?')
588588
# The size taken up by the 'formatcode' dynamic array
589589
totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1)
590590
support.check_sizeof(self, struct.Struct(format_str), totalsize)

Modules/_struct.c

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ typedef struct {
7070
formatcode *s_codes;
7171
PyObject *s_format;
7272
PyObject *weakreflist; /* List of weak references */
73+
bool init_called;
7374
} PyStructObject;
7475

7576
#define PyStructObject_CAST(op) ((PyStructObject *)(op))
@@ -1757,30 +1758,61 @@ prepare_s(PyStructObject *self)
17571758
return -1;
17581759
}
17591760

1761+
static int
1762+
actual___init___impl(PyStructObject *self, PyObject *format)
1763+
{
1764+
if (PyUnicode_Check(format)) {
1765+
format = PyUnicode_AsASCIIString(format);
1766+
if (format == NULL)
1767+
return -1;
1768+
}
1769+
else {
1770+
Py_INCREF(format);
1771+
}
1772+
if (!PyBytes_Check(format)) {
1773+
Py_DECREF(format);
1774+
PyErr_Format(PyExc_TypeError,
1775+
"Struct() argument 1 must be a str or bytes object, "
1776+
"not %.200s",
1777+
_PyType_Name(Py_TYPE(format)));
1778+
return -1;
1779+
}
1780+
Py_SETREF(self->s_format, format);
1781+
if (prepare_s(self)) {
1782+
return -1;
1783+
}
1784+
return 0;
1785+
}
1786+
17601787
static PyObject *
17611788
s_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
17621789
{
1763-
PyObject *self;
1790+
PyStructObject *self;
17641791

1765-
if (PyTuple_GET_SIZE(args) != 1
1792+
if ((PyTuple_GET_SIZE(args) != 1 || kwds)
17661793
&& PyErr_WarnEx(PyExc_DeprecationWarning,
1767-
"Struct().__new__() has one required argument", 1))
1794+
"Struct.__new__() has one positional argument", 1))
17681795
{
17691796
return NULL;
17701797
}
17711798
assert(type != NULL);
17721799
allocfunc alloc_func = PyType_GetSlot(type, Py_tp_alloc);
17731800
assert(alloc_func != NULL);
1774-
1775-
self = alloc_func(type, 0);
1801+
self = (PyStructObject *)alloc_func(type, 0);
17761802
if (self != NULL) {
1777-
PyStructObject *s = (PyStructObject*)self;
1778-
s->s_format = Py_NewRef(Py_None);
1779-
s->s_codes = NULL;
1780-
s->s_size = -1;
1781-
s->s_len = -1;
1803+
self->s_format = Py_NewRef(Py_None);
1804+
self->s_codes = NULL;
1805+
self->s_size = -1;
1806+
self->s_len = -1;
1807+
self->init_called = false;
1808+
if (PyTuple_GET_SIZE(args) > 0) {
1809+
if (actual___init___impl(self, PyTuple_GET_ITEM(args, 0))) {
1810+
Py_DECREF(self);
1811+
return NULL;
1812+
}
1813+
}
17821814
}
1783-
return self;
1815+
return (PyObject *)self;
17841816
}
17851817

17861818
/*[clinic input]
@@ -1800,37 +1832,21 @@ static int
18001832
Struct___init___impl(PyStructObject *self, PyObject *format)
18011833
/*[clinic end generated code: output=b8e80862444e92d0 input=192a4575a3dde802]*/
18021834
{
1803-
int ret = 0;
1804-
1805-
if (self->s_codes
1835+
if (!self->init_called) {
1836+
if (!self->s_codes && actual___init___impl(self, format)) {
1837+
return -1;
1838+
}
1839+
self->init_called = true;
1840+
return 0;
1841+
}
1842+
if ((self->s_codes && self->init_called)
18061843
&& PyErr_WarnEx(PyExc_DeprecationWarning,
18071844
("Explicit call of __init__() on "
18081845
"initialized Struct() is deprecated"), 1))
18091846
{
18101847
return -1;
18111848
}
1812-
if (PyUnicode_Check(format)) {
1813-
format = PyUnicode_AsASCIIString(format);
1814-
if (format == NULL)
1815-
return -1;
1816-
}
1817-
else {
1818-
Py_INCREF(format);
1819-
}
1820-
1821-
if (!PyBytes_Check(format)) {
1822-
Py_DECREF(format);
1823-
PyErr_Format(PyExc_TypeError,
1824-
"Struct() argument 1 must be a str or bytes object, "
1825-
"not %.200s",
1826-
_PyType_Name(Py_TYPE(format)));
1827-
return -1;
1828-
}
1829-
1830-
Py_SETREF(self->s_format, format);
1831-
1832-
ret = prepare_s(self);
1833-
return ret;
1849+
return actual___init___impl(self, format);
18341850
}
18351851

18361852
static int
@@ -2473,9 +2489,7 @@ static PyType_Slot PyStructType_slots[] = {
24732489
{Py_tp_members, s_members},
24742490
{Py_tp_getset, s_getsetlist},
24752491
{Py_tp_init, Struct___init__},
2476-
{Py_tp_alloc, PyType_GenericAlloc},
24772492
{Py_tp_new, s_new},
2478-
{Py_tp_free, PyObject_GC_Del},
24792493
{0, 0},
24802494
};
24812495

0 commit comments

Comments
 (0)