Skip to content

Commit cab1298

Browse files
gh-101819: Adapt _io.PyWindowsConsoleIO_Type to heap type (#104197)
1 parent 3952379 commit cab1298

File tree

4 files changed

+51
-70
lines changed

4 files changed

+51
-70
lines changed

Modules/_io/_iomodule.c

+11-11
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
321321
#ifdef HAVE_WINDOWS_CONSOLE_IO
322322
const PyConfig *config = _Py_GetConfig();
323323
if (!config->legacy_windows_stdio && _PyIO_get_console_type(path_or_fd) != '\0') {
324-
RawIO_class = (PyObject *)&PyWindowsConsoleIO_Type;
324+
RawIO_class = (PyObject *)state->PyWindowsConsoleIO_Type;
325325
encoding = "utf-8";
326326
}
327327
#endif
@@ -595,6 +595,9 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
595595
Py_VISIT(state->PyStringIO_Type);
596596
Py_VISIT(state->PyTextIOBase_Type);
597597
Py_VISIT(state->PyTextIOWrapper_Type);
598+
#ifdef HAVE_WINDOWS_CONSOLE_IO
599+
Py_VISIT(state->PyWindowsConsoleIO_Type);
600+
#endif
598601
return 0;
599602
}
600603

@@ -619,6 +622,9 @@ iomodule_clear(PyObject *mod) {
619622
Py_CLEAR(state->PyStringIO_Type);
620623
Py_CLEAR(state->PyTextIOBase_Type);
621624
Py_CLEAR(state->PyTextIOWrapper_Type);
625+
#ifdef HAVE_WINDOWS_CONSOLE_IO
626+
Py_CLEAR(state->PyWindowsConsoleIO_Type);
627+
#endif
622628
return 0;
623629
}
624630

@@ -668,22 +674,12 @@ static PyTypeObject* static_types[] = {
668674

669675
// PyRawIOBase_Type(PyIOBase_Type) subclasses
670676
&_PyBytesIOBuffer_Type,
671-
#ifdef HAVE_WINDOWS_CONSOLE_IO
672-
&PyWindowsConsoleIO_Type,
673-
#endif
674677
};
675678

676679

677680
PyStatus
678681
_PyIO_InitTypes(PyInterpreterState *interp)
679682
{
680-
#ifdef HAVE_WINDOWS_CONSOLE_IO
681-
if (_Py_IsMainInterpreter(interp)) {
682-
// Set type base classes
683-
PyWindowsConsoleIO_Type.tp_base = &PyRawIOBase_Type;
684-
}
685-
#endif
686-
687683
for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
688684
PyTypeObject *type = static_types[i];
689685
if (_PyStaticType_InitBuiltin(interp, type) < 0) {
@@ -777,6 +773,10 @@ PyInit__io(void)
777773
// PyRawIOBase_Type(PyIOBase_Type) subclasses
778774
state->PyBytesIOBuffer_Type = (PyTypeObject *)Py_NewRef(&_PyBytesIOBuffer_Type);
779775
ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, state->PyRawIOBase_Type);
776+
#ifdef MS_WINDOWS
777+
ADD_TYPE(m, state->PyWindowsConsoleIO_Type, &winconsoleio_spec,
778+
state->PyRawIOBase_Type);
779+
#endif
780780

781781
// PyTextIOBase_Type(PyIOBase_Type) subclasses
782782
ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, state->PyTextIOBase_Type);

Modules/_io/_iomodule.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ extern PyType_Spec stringio_spec;
2626
extern PyType_Spec textiowrapper_spec;
2727

2828
#ifdef HAVE_WINDOWS_CONSOLE_IO
29-
extern PyTypeObject PyWindowsConsoleIO_Type;
30-
#endif /* HAVE_WINDOWS_CONSOLE_IO */
29+
extern PyType_Spec winconsoleio_spec;
30+
#endif
3131

3232
/* These functions are used as METH_NOARGS methods, are normally called
3333
* with args=NULL, and return a new reference.
@@ -157,6 +157,9 @@ typedef struct {
157157
PyTypeObject *PyStringIO_Type;
158158
PyTypeObject *PyTextIOBase_Type;
159159
PyTypeObject *PyTextIOWrapper_Type;
160+
#ifdef MS_WINDOWS
161+
PyTypeObject *PyWindowsConsoleIO_Type;
162+
#endif
160163
} _PyIO_State;
161164

162165
#define IO_MOD_STATE(mod) ((_PyIO_State *)PyModule_GetState(mod))

Modules/_io/winconsoleio.c

+35-56
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,9 @@ char _PyIO_get_console_type(PyObject *path_or_fd) {
137137

138138
/*[clinic input]
139139
module _io
140-
class _io._WindowsConsoleIO "winconsoleio *" "&PyWindowsConsoleIO_Type"
140+
class _io._WindowsConsoleIO "winconsoleio *" "clinic_state()->PyWindowsConsoleIO_Type"
141141
[clinic start generated code]*/
142-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e897fdc1fba4e131]*/
142+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=05526e723011ab36]*/
143143

144144
typedef struct {
145145
PyObject_HEAD
@@ -156,8 +156,6 @@ typedef struct {
156156
wchar_t wbuf;
157157
} winconsoleio;
158158

159-
PyTypeObject PyWindowsConsoleIO_Type;
160-
161159
int
162160
_PyWindowsConsoleIO_closed(PyObject *self)
163161
{
@@ -265,7 +263,10 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
265263
int fd_is_own = 0;
266264
HANDLE handle = NULL;
267265

268-
assert(PyObject_TypeCheck(self, (PyTypeObject *)&PyWindowsConsoleIO_Type));
266+
#ifdef Py_DEBUG
267+
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
268+
assert(PyObject_TypeCheck(self, state->PyWindowsConsoleIO_Type));
269+
#endif
269270
if (self->fd >= 0) {
270271
if (self->closefd) {
271272
/* Have to close the existing file first. */
@@ -417,6 +418,7 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
417418
static int
418419
winconsoleio_traverse(winconsoleio *self, visitproc visit, void *arg)
419420
{
421+
Py_VISIT(Py_TYPE(self));
420422
Py_VISIT(self->dict);
421423
return 0;
422424
}
@@ -431,14 +433,16 @@ winconsoleio_clear(winconsoleio *self)
431433
static void
432434
winconsoleio_dealloc(winconsoleio *self)
433435
{
436+
PyTypeObject *tp = Py_TYPE(self);
434437
self->finalizing = 1;
435438
if (_PyIOBase_finalize((PyObject *) self) < 0)
436439
return;
437440
_PyObject_GC_UNTRACK(self);
438441
if (self->weakreflist != NULL)
439442
PyObject_ClearWeakRefs((PyObject *) self);
440443
Py_CLEAR(self->dict);
441-
Py_TYPE(self)->tp_free((PyObject *)self);
444+
tp->tp_free((PyObject *)self);
445+
Py_DECREF(tp);
442446
}
443447

444448
static PyObject *
@@ -1078,7 +1082,9 @@ _io__WindowsConsoleIO_isatty_impl(winconsoleio *self)
10781082
Py_RETURN_TRUE;
10791083
}
10801084

1085+
#define clinic_state() (IO_STATE())
10811086
#include "clinic/winconsoleio.c.h"
1087+
#undef clinic_state
10821088

10831089
static PyMethodDef winconsoleio_methods[] = {
10841090
_IO__WINDOWSCONSOLEIO_READ_METHODDEF
@@ -1124,59 +1130,32 @@ static PyGetSetDef winconsoleio_getsetlist[] = {
11241130
static PyMemberDef winconsoleio_members[] = {
11251131
{"_blksize", T_UINT, offsetof(winconsoleio, blksize), 0},
11261132
{"_finalizing", T_BOOL, offsetof(winconsoleio, finalizing), 0},
1133+
{"__weaklistoffset__", T_PYSSIZET, offsetof(winconsoleio, weakreflist), READONLY},
1134+
{"__dictoffset__", T_PYSSIZET, offsetof(winconsoleio, dict), READONLY},
11271135
{NULL}
11281136
};
11291137

1130-
PyTypeObject PyWindowsConsoleIO_Type = {
1131-
PyVarObject_HEAD_INIT(NULL, 0)
1132-
"_io._WindowsConsoleIO",
1133-
sizeof(winconsoleio),
1134-
0,
1135-
(destructor)winconsoleio_dealloc, /* tp_dealloc */
1136-
0, /* tp_vectorcall_offset */
1137-
0, /* tp_getattr */
1138-
0, /* tp_setattr */
1139-
0, /* tp_as_async */
1140-
(reprfunc)winconsoleio_repr, /* tp_repr */
1141-
0, /* tp_as_number */
1142-
0, /* tp_as_sequence */
1143-
0, /* tp_as_mapping */
1144-
0, /* tp_hash */
1145-
0, /* tp_call */
1146-
0, /* tp_str */
1147-
PyObject_GenericGetAttr, /* tp_getattro */
1148-
0, /* tp_setattro */
1149-
0, /* tp_as_buffer */
1150-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1151-
| Py_TPFLAGS_HAVE_GC, /* tp_flags */
1152-
_io__WindowsConsoleIO___init____doc__, /* tp_doc */
1153-
(traverseproc)winconsoleio_traverse, /* tp_traverse */
1154-
(inquiry)winconsoleio_clear, /* tp_clear */
1155-
0, /* tp_richcompare */
1156-
offsetof(winconsoleio, weakreflist), /* tp_weaklistoffset */
1157-
0, /* tp_iter */
1158-
0, /* tp_iternext */
1159-
winconsoleio_methods, /* tp_methods */
1160-
winconsoleio_members, /* tp_members */
1161-
winconsoleio_getsetlist, /* tp_getset */
1162-
0, /* tp_base */
1163-
0, /* tp_dict */
1164-
0, /* tp_descr_get */
1165-
0, /* tp_descr_set */
1166-
offsetof(winconsoleio, dict), /* tp_dictoffset */
1167-
_io__WindowsConsoleIO___init__, /* tp_init */
1168-
PyType_GenericAlloc, /* tp_alloc */
1169-
winconsoleio_new, /* tp_new */
1170-
PyObject_GC_Del, /* tp_free */
1171-
0, /* tp_is_gc */
1172-
0, /* tp_bases */
1173-
0, /* tp_mro */
1174-
0, /* tp_cache */
1175-
0, /* tp_subclasses */
1176-
0, /* tp_weaklist */
1177-
0, /* tp_del */
1178-
0, /* tp_version_tag */
1179-
0, /* tp_finalize */
1138+
static PyType_Slot winconsoleio_slots[] = {
1139+
{Py_tp_dealloc, winconsoleio_dealloc},
1140+
{Py_tp_repr, winconsoleio_repr},
1141+
{Py_tp_getattro, PyObject_GenericGetAttr},
1142+
{Py_tp_doc, (void *)_io__WindowsConsoleIO___init____doc__},
1143+
{Py_tp_traverse, winconsoleio_traverse},
1144+
{Py_tp_clear, winconsoleio_clear},
1145+
{Py_tp_methods, winconsoleio_methods},
1146+
{Py_tp_members, winconsoleio_members},
1147+
{Py_tp_getset, winconsoleio_getsetlist},
1148+
{Py_tp_init, _io__WindowsConsoleIO___init__},
1149+
{Py_tp_new, winconsoleio_new},
1150+
{0, NULL},
1151+
};
1152+
1153+
PyType_Spec winconsoleio_spec = {
1154+
.name = "_io._WindowsConsoleIO",
1155+
.basicsize = sizeof(winconsoleio),
1156+
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
1157+
Py_TPFLAGS_IMMUTABLETYPE),
1158+
.slots = winconsoleio_slots,
11801159
};
11811160

11821161
#endif /* HAVE_WINDOWS_CONSOLE_IO */

Tools/c-analyzer/cpython/globals-to-fix.tsv

-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,6 @@ Modules/_io/bytesio.c - _PyBytesIOBuffer_Type -
322322
Modules/_io/iobase.c - PyIOBase_Type -
323323
Modules/_io/iobase.c - PyRawIOBase_Type -
324324
Modules/_io/textio.c - PyTextIOBase_Type -
325-
Modules/_io/winconsoleio.c - PyWindowsConsoleIO_Type -
326325
Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type -
327326
Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type -
328327
Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_Type -

0 commit comments

Comments
 (0)