Skip to content

Commit dfc1e9e

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 * Add the defining class to methods: * _io.BytesIO.getbuffer() * _io.FileIO.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 81fc135 commit dfc1e9e

File tree

9 files changed

+92
-37
lines changed

9 files changed

+92
-37
lines changed

Modules/_io/_iomodule.c

+27-8
Original file line numberDiff line numberDiff line change
@@ -583,13 +583,18 @@ 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);
594599
return 0;
595600
}
@@ -604,13 +609,18 @@ iomodule_clear(PyObject *mod) {
604609
Py_CLEAR(state->locale_module);
605610
Py_CLEAR(state->unsupported_operation);
606611

612+
Py_CLEAR(state->PyIncrementalNewlineDecoder_Type);
613+
Py_CLEAR(state->PyRawIOBase_Type);
614+
Py_CLEAR(state->PyBufferedIOBase_Type);
607615
Py_CLEAR(state->PyBufferedRWPair_Type);
608616
Py_CLEAR(state->PyBufferedRandom_Type);
609617
Py_CLEAR(state->PyBufferedReader_Type);
610618
Py_CLEAR(state->PyBufferedWriter_Type);
619+
Py_CLEAR(state->PyBytesIOBuffer_Type);
611620
Py_CLEAR(state->PyBytesIO_Type);
612621
Py_CLEAR(state->PyFileIO_Type);
613622
Py_CLEAR(state->PyStringIO_Type);
623+
Py_CLEAR(state->PyTextIOBase_Type);
614624
Py_CLEAR(state->PyTextIOWrapper_Type);
615625
return 0;
616626
}
@@ -749,24 +759,33 @@ PyInit__io(void)
749759
}
750760
}
751761

762+
// Base classes
763+
state->PyIncrementalNewlineDecoder_Type = (PyTypeObject *)Py_NewRef(&PyIncrementalNewlineDecoder_Type);
764+
765+
// PyIOBase_Type subclasses
766+
state->PyRawIOBase_Type = (PyTypeObject *)Py_NewRef(&PyRawIOBase_Type);
767+
state->PyBufferedIOBase_Type = (PyTypeObject *)Py_NewRef(&PyBufferedIOBase_Type);
768+
state->PyTextIOBase_Type = (PyTypeObject *)Py_NewRef(&PyTextIOBase_Type);
769+
752770
// PyBufferedIOBase_Type(PyIOBase_Type) subclasses
753-
ADD_TYPE(m, state->PyBytesIO_Type, &bytesio_spec, &PyBufferedIOBase_Type);
771+
ADD_TYPE(m, state->PyBytesIO_Type, &bytesio_spec, state->PyBufferedIOBase_Type);
754772
ADD_TYPE(m, state->PyBufferedWriter_Type, &bufferedwriter_spec,
755-
&PyBufferedIOBase_Type);
773+
state->PyBufferedIOBase_Type);
756774
ADD_TYPE(m, state->PyBufferedReader_Type, &bufferedreader_spec,
757-
&PyBufferedIOBase_Type);
775+
state->PyBufferedIOBase_Type);
758776
ADD_TYPE(m, state->PyBufferedRWPair_Type, &bufferedrwpair_spec,
759-
&PyBufferedIOBase_Type);
777+
state->PyBufferedIOBase_Type);
760778
ADD_TYPE(m, state->PyBufferedRandom_Type, &bufferedrandom_spec,
761-
&PyBufferedIOBase_Type);
779+
state->PyBufferedIOBase_Type);
762780

763781
// PyRawIOBase_Type(PyIOBase_Type) subclasses
764-
ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, &PyRawIOBase_Type);
782+
state->PyBytesIOBuffer_Type = (PyTypeObject *)Py_NewRef(&_PyBytesIOBuffer_Type);
783+
ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, state->PyRawIOBase_Type);
765784

766785
// PyTextIOBase_Type(PyIOBase_Type) subclasses
767-
ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, &PyTextIOBase_Type);
786+
ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, state->PyTextIOBase_Type);
768787
ADD_TYPE(m, state->PyTextIOWrapper_Type, &textiowrapper_spec,
769-
&PyTextIOBase_Type);
788+
state->PyTextIOBase_Type);
770789

771790
state->initialized = 1;
772791

Modules/_io/_iomodule.h

+14
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,13 +148,18 @@ 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;
158164
} _PyIO_State;
159165

@@ -168,6 +174,14 @@ get_io_state(PyObject *module)
168174
return (_PyIO_State *)state;
169175
}
170176

177+
static inline _PyIO_State *
178+
get_io_state_by_cls(PyTypeObject *cls)
179+
{
180+
void *state = _PyType_GetModuleState(cls);
181+
assert(state != NULL);
182+
return (_PyIO_State *)state;
183+
}
184+
171185
static inline _PyIO_State *
172186
find_io_state_by_def(PyTypeObject *type)
173187
{

Modules/_io/bufferedio.c

+1-1
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

+7-3
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

+9-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/_io/clinic/fileio.c.h

+9-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/_io/fileio.c

+9-4
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

+3-2
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;

Modules/_io/textio.c

+13-9
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818

1919
/*[clinic input]
2020
module _io
21-
class _io.IncrementalNewlineDecoder "nldecoder_object *" "&PyIncrementalNewlineDecoder_Type"
21+
class _io.IncrementalNewlineDecoder "nldecoder_object *" "clinic_state()->PyIncrementalNewlineDecoder_Type"
2222
class _io.TextIOWrapper "textio *" "clinic_state()->TextIOWrapper_Type"
2323
[clinic start generated code]*/
24-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d3f032e90f74c8f2]*/
24+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=81f67cf54eaa6001]*/
2525

2626
/* TextIOBase */
2727

@@ -872,8 +872,9 @@ _textiowrapper_set_decoder(textio *self, PyObject *codec_info,
872872
return -1;
873873

874874
if (self->readuniversal) {
875+
_PyIO_State *state = self->state;
875876
PyObject *incrementalDecoder = PyObject_CallFunctionObjArgs(
876-
(PyObject *)&PyIncrementalNewlineDecoder_Type,
877+
(PyObject *)state->PyIncrementalNewlineDecoder_Type,
877878
self->decoder, self->readtranslate ? Py_True : Py_False, NULL);
878879
if (incrementalDecoder == NULL)
879880
return -1;
@@ -884,11 +885,12 @@ _textiowrapper_set_decoder(textio *self, PyObject *codec_info,
884885
}
885886

886887
static PyObject*
887-
_textiowrapper_decode(PyObject *decoder, PyObject *bytes, int eof)
888+
_textiowrapper_decode(_PyIO_State *state, PyObject *decoder, PyObject *bytes,
889+
int eof)
888890
{
889891
PyObject *chars;
890892

891-
if (Py_IS_TYPE(decoder, &PyIncrementalNewlineDecoder_Type))
893+
if (Py_IS_TYPE(decoder, state->PyIncrementalNewlineDecoder_Type))
892894
chars = _PyIncrementalNewlineDecoder_decode(decoder, bytes, eof);
893895
else
894896
chars = PyObject_CallMethodObjArgs(decoder, &_Py_ID(decode), bytes,
@@ -1167,6 +1169,8 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
11671169
self->buffer = Py_NewRef(buffer);
11681170

11691171
/* Build the decoder object */
1172+
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1173+
self->state = state;
11701174
if (_textiowrapper_set_decoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0)
11711175
goto error;
11721176

@@ -1177,7 +1181,6 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
11771181
/* Finished sorting out the codec details */
11781182
Py_CLEAR(codec_info);
11791183

1180-
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
11811184
if (Py_IS_TYPE(buffer, state->PyBufferedReader_Type) ||
11821185
Py_IS_TYPE(buffer, state->PyBufferedWriter_Type) ||
11831186
Py_IS_TYPE(buffer, state->PyBufferedRandom_Type))
@@ -1214,7 +1217,6 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
12141217
goto error;
12151218
}
12161219

1217-
self->state = state;
12181220
self->ok = 1;
12191221
return 0;
12201222

@@ -1843,7 +1845,8 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint)
18431845
nbytes = input_chunk_buf.len;
18441846
eof = (nbytes == 0);
18451847

1846-
decoded_chars = _textiowrapper_decode(self->decoder, input_chunk, eof);
1848+
decoded_chars = _textiowrapper_decode(self->state, self->decoder,
1849+
input_chunk, eof);
18471850
PyBuffer_Release(&input_chunk_buf);
18481851
if (decoded_chars == NULL)
18491852
goto fail;
@@ -1913,7 +1916,8 @@ _io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n)
19131916
if (bytes == NULL)
19141917
goto fail;
19151918

1916-
if (Py_IS_TYPE(self->decoder, &PyIncrementalNewlineDecoder_Type))
1919+
_PyIO_State *state = self->state;
1920+
if (Py_IS_TYPE(self->decoder, state->PyIncrementalNewlineDecoder_Type))
19171921
decoded = _PyIncrementalNewlineDecoder_decode(self->decoder,
19181922
bytes, 1);
19191923
else

0 commit comments

Comments
 (0)