Skip to content

Commit 46ee857

Browse files
gh-101819: Prepare to modernize the _io extension
* Add references to static types to _PyIO_State: * PyBufferedIOBase_Type * PyBytesIOBuffer_Type * PyIncrementalNewlineDecoder_Type * PyRawIOBase_Type * PyTextIOBase_Type * PyWindowsConsoleIO_Type * Add the defining class to methods: * _io.BytesIO.getbuffer() * _io.FileIO.close() * _io._WindowsConsoleIO.close() * Add get_io_state_by_cls() function. * Add state parameter to _textiowrapper_decode() * _io_TextIOWrapper___init__() now sets self->state before calling _textiowrapper_set_decoder(). Co-Authored-by: Erlend E. Aasland <[email protected]>
1 parent c9ecd3e commit 46ee857

File tree

11 files changed

+127
-50
lines changed

11 files changed

+127
-50
lines changed

Modules/_io/_iomodule.c

Lines changed: 37 additions & 9 deletions
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
@@ -583,14 +583,22 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
583583
Py_VISIT(state->locale_module);
584584
Py_VISIT(state->unsupported_operation);
585585

586+
Py_VISIT(state->PyIncrementalNewlineDecoder_Type);
587+
Py_VISIT(state->PyRawIOBase_Type);
588+
Py_VISIT(state->PyBufferedIOBase_Type);
586589
Py_VISIT(state->PyBufferedRWPair_Type);
587590
Py_VISIT(state->PyBufferedRandom_Type);
588591
Py_VISIT(state->PyBufferedReader_Type);
589592
Py_VISIT(state->PyBufferedWriter_Type);
593+
Py_VISIT(state->PyBytesIOBuffer_Type);
590594
Py_VISIT(state->PyBytesIO_Type);
591595
Py_VISIT(state->PyFileIO_Type);
592596
Py_VISIT(state->PyStringIO_Type);
597+
Py_VISIT(state->PyTextIOBase_Type);
593598
Py_VISIT(state->PyTextIOWrapper_Type);
599+
#ifdef HAVE_WINDOWS_CONSOLE_IO
600+
Py_VISIT(state->PyWindowsConsoleIO_Type);
601+
#endif
594602
return 0;
595603
}
596604

@@ -604,14 +612,22 @@ iomodule_clear(PyObject *mod) {
604612
Py_CLEAR(state->locale_module);
605613
Py_CLEAR(state->unsupported_operation);
606614

615+
Py_CLEAR(state->PyIncrementalNewlineDecoder_Type);
616+
Py_CLEAR(state->PyRawIOBase_Type);
617+
Py_CLEAR(state->PyBufferedIOBase_Type);
607618
Py_CLEAR(state->PyBufferedRWPair_Type);
608619
Py_CLEAR(state->PyBufferedRandom_Type);
609620
Py_CLEAR(state->PyBufferedReader_Type);
610621
Py_CLEAR(state->PyBufferedWriter_Type);
622+
Py_CLEAR(state->PyBytesIOBuffer_Type);
611623
Py_CLEAR(state->PyBytesIO_Type);
612624
Py_CLEAR(state->PyFileIO_Type);
613625
Py_CLEAR(state->PyStringIO_Type);
626+
Py_CLEAR(state->PyTextIOBase_Type);
614627
Py_CLEAR(state->PyTextIOWrapper_Type);
628+
#ifdef HAVE_WINDOWS_CONSOLE_IO
629+
Py_CLEAR(state->PyWindowsConsoleIO_Type);
630+
#endif
615631
return 0;
616632
}
617633

@@ -749,24 +765,36 @@ PyInit__io(void)
749765
}
750766
}
751767

768+
// Base classes
769+
state->PyIncrementalNewlineDecoder_Type = (PyTypeObject *)Py_NewRef(&PyIncrementalNewlineDecoder_Type);
770+
771+
// PyIOBase_Type subclasses
772+
state->PyRawIOBase_Type = (PyTypeObject *)Py_NewRef(&PyRawIOBase_Type);
773+
state->PyBufferedIOBase_Type = (PyTypeObject *)Py_NewRef(&PyBufferedIOBase_Type);
774+
state->PyTextIOBase_Type = (PyTypeObject *)Py_NewRef(&PyTextIOBase_Type);
775+
752776
// PyBufferedIOBase_Type(PyIOBase_Type) subclasses
753-
ADD_TYPE(m, state->PyBytesIO_Type, &bytesio_spec, &PyBufferedIOBase_Type);
777+
ADD_TYPE(m, state->PyBytesIO_Type, &bytesio_spec, state->PyBufferedIOBase_Type);
754778
ADD_TYPE(m, state->PyBufferedWriter_Type, &bufferedwriter_spec,
755-
&PyBufferedIOBase_Type);
779+
state->PyBufferedIOBase_Type);
756780
ADD_TYPE(m, state->PyBufferedReader_Type, &bufferedreader_spec,
757-
&PyBufferedIOBase_Type);
781+
state->PyBufferedIOBase_Type);
758782
ADD_TYPE(m, state->PyBufferedRWPair_Type, &bufferedrwpair_spec,
759-
&PyBufferedIOBase_Type);
783+
state->PyBufferedIOBase_Type);
760784
ADD_TYPE(m, state->PyBufferedRandom_Type, &bufferedrandom_spec,
761-
&PyBufferedIOBase_Type);
785+
state->PyBufferedIOBase_Type);
762786

763787
// PyRawIOBase_Type(PyIOBase_Type) subclasses
764-
ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, &PyRawIOBase_Type);
788+
state->PyBytesIOBuffer_Type = (PyTypeObject *)Py_NewRef(&_PyBytesIOBuffer_Type);
789+
#ifdef HAVE_WINDOWS_CONSOLE_IO
790+
state->PyWindowsConsoleIO_Type = (PyTypeObject *)Py_NewRef(&PyWindowsConsoleIO_Type);
791+
#endif
792+
ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, state->PyRawIOBase_Type);
765793

766794
// PyTextIOBase_Type(PyIOBase_Type) subclasses
767-
ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, &PyTextIOBase_Type);
795+
ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, state->PyTextIOBase_Type);
768796
ADD_TYPE(m, state->PyTextIOWrapper_Type, &textiowrapper_spec,
769-
&PyTextIOBase_Type);
797+
state->PyTextIOBase_Type);
770798

771799
state->initialized = 1;
772800

Modules/_io/_iomodule.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "exports.h"
66

77
#include "pycore_moduleobject.h" // _PyModule_GetState()
8+
#include "pycore_typeobject.h" // _PyType_GetModuleState()
89
#include "structmember.h"
910

1011
/* ABCs */
@@ -147,14 +148,22 @@ typedef struct {
147148
PyObject *unsupported_operation;
148149

149150
/* Types */
151+
PyTypeObject *PyIncrementalNewlineDecoder_Type;
152+
PyTypeObject *PyRawIOBase_Type;
153+
PyTypeObject *PyBufferedIOBase_Type;
150154
PyTypeObject *PyBufferedRWPair_Type;
151155
PyTypeObject *PyBufferedRandom_Type;
152156
PyTypeObject *PyBufferedReader_Type;
153157
PyTypeObject *PyBufferedWriter_Type;
158+
PyTypeObject *PyBytesIOBuffer_Type;
154159
PyTypeObject *PyBytesIO_Type;
155160
PyTypeObject *PyFileIO_Type;
156161
PyTypeObject *PyStringIO_Type;
162+
PyTypeObject *PyTextIOBase_Type;
157163
PyTypeObject *PyTextIOWrapper_Type;
164+
#ifdef HAVE_WINDOWS_CONSOLE_IO
165+
PyTypeObject *PyWindowsConsoleIO_Type;
166+
#endif
158167
} _PyIO_State;
159168

160169
#define IO_MOD_STATE(mod) ((_PyIO_State *)PyModule_GetState(mod))
@@ -168,6 +177,14 @@ get_io_state(PyObject *module)
168177
return (_PyIO_State *)state;
169178
}
170179

180+
static inline _PyIO_State *
181+
get_io_state_by_cls(PyTypeObject *cls)
182+
{
183+
void *state = _PyType_GetModuleState(cls);
184+
assert(state != NULL);
185+
return (_PyIO_State *)state;
186+
}
187+
171188
static inline _PyIO_State *
172189
find_io_state_by_def(PyTypeObject *type)
173190
{

Modules/_io/bufferedio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2231,7 +2231,7 @@ bufferedrwpair_close(rwpair *self, PyObject *Py_UNUSED(ignored))
22312231
}
22322232
else {
22332233
Py_DECREF(ret);
2234-
}
2234+
}
22352235
ret = _forward_call(self->reader, &_Py_ID(close), NULL);
22362236
if (exc != NULL) {
22372237
_PyErr_ChainExceptions1(exc);

Modules/_io/bytesio.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,14 +308,18 @@ _io_BytesIO_flush_impl(bytesio *self)
308308
/*[clinic input]
309309
_io.BytesIO.getbuffer
310310
311+
cls: defining_class
312+
/
313+
311314
Get a read-write view over the contents of the BytesIO object.
312315
[clinic start generated code]*/
313316

314317
static PyObject *
315-
_io_BytesIO_getbuffer_impl(bytesio *self)
316-
/*[clinic end generated code: output=72cd7c6e13aa09ed input=8f738ef615865176]*/
318+
_io_BytesIO_getbuffer_impl(bytesio *self, PyTypeObject *cls)
319+
/*[clinic end generated code: output=045091d7ce87fe4e input=0668fbb48f95dffa]*/
317320
{
318-
PyTypeObject *type = &_PyBytesIOBuffer_Type;
321+
_PyIO_State *state = get_io_state_by_cls(cls);
322+
PyTypeObject *type = state->PyBytesIOBuffer_Type;
319323
bytesiobuf *buf;
320324
PyObject *view;
321325

Modules/_io/clinic/bytesio.c.h

Lines changed: 9 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/_io/clinic/fileio.c.h

Lines changed: 9 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/_io/clinic/winconsoleio.c.h

Lines changed: 9 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/_io/fileio.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,25 +130,30 @@ internal_close(fileio *self)
130130
/*[clinic input]
131131
_io.FileIO.close
132132
133+
cls: defining_class
134+
/
135+
133136
Close the file.
134137
135138
A closed file cannot be used for further I/O operations. close() may be
136139
called more than once without error.
137140
[clinic start generated code]*/
138141

139142
static PyObject *
140-
_io_FileIO_close_impl(fileio *self)
141-
/*[clinic end generated code: output=7737a319ef3bad0b input=f35231760d54a522]*/
143+
_io_FileIO_close_impl(fileio *self, PyTypeObject *cls)
144+
/*[clinic end generated code: output=c30cbe9d1f23ca58 input=70da49e63db7c64d]*/
142145
{
143146
PyObject *res;
144-
PyObject *exc;
145147
int rc;
146-
res = PyObject_CallMethodOneArg((PyObject*)&PyRawIOBase_Type,
148+
_PyIO_State *state = get_io_state_by_cls(cls);
149+
res = PyObject_CallMethodOneArg((PyObject*)state->PyRawIOBase_Type,
147150
&_Py_ID(close), (PyObject *)self);
148151
if (!self->closefd) {
149152
self->fd = -1;
150153
return res;
151154
}
155+
156+
PyObject *exc;
152157
if (res == NULL) {
153158
exc = PyErr_GetRaisedException();
154159
}

Modules/_io/stringio.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -716,9 +716,10 @@ _io_StringIO___init___impl(stringio *self, PyObject *value,
716716
self->writenl = Py_NewRef(self->readnl);
717717
}
718718

719+
_PyIO_State *module_state = find_io_state_by_def(Py_TYPE(self));
719720
if (self->readuniversal) {
720721
self->decoder = PyObject_CallFunctionObjArgs(
721-
(PyObject *)&PyIncrementalNewlineDecoder_Type,
722+
(PyObject *)module_state->PyIncrementalNewlineDecoder_Type,
722723
Py_None, self->readtranslate ? Py_True : Py_False, NULL);
723724
if (self->decoder == NULL)
724725
return -1;
@@ -750,7 +751,7 @@ _io_StringIO___init___impl(stringio *self, PyObject *value,
750751
self->state = STATE_ACCUMULATING;
751752
}
752753
self->pos = 0;
753-
self->module_state = find_io_state_by_def(Py_TYPE(self));
754+
self->module_state = module_state;
754755
self->closed = 0;
755756
self->ok = 1;
756757
return 0;

0 commit comments

Comments
 (0)