1010#define PY_SSIZE_T_CLEAN
1111#include "Python.h"
1212#include "_iomodule.h"
13- #include "pycore_moduleobject.h" // _PyModule_GetState()
1413#include "pycore_pystate.h" // _PyInterpreterState_GET()
1514
1615#ifdef HAVE_SYS_TYPES_H
@@ -315,8 +314,9 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
315314 }
316315
317316 /* Create the Raw file stream */
317+ _PyIO_State * state = get_io_state (module );
318318 {
319- PyObject * RawIO_class = (PyObject * )& PyFileIO_Type ;
319+ PyObject * RawIO_class = (PyObject * )state -> PyFileIO_Type ;
320320#ifdef MS_WINDOWS
321321 const PyConfig * config = _Py_GetConfig ();
322322 if (!config -> legacy_windows_stdio && _PyIO_get_console_type (path_or_fd ) != '\0' ) {
@@ -390,12 +390,15 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
390390 {
391391 PyObject * Buffered_class ;
392392
393- if (updating )
394- Buffered_class = (PyObject * )& PyBufferedRandom_Type ;
395- else if (creating || writing || appending )
396- Buffered_class = (PyObject * )& PyBufferedWriter_Type ;
397- else if (reading )
398- Buffered_class = (PyObject * )& PyBufferedReader_Type ;
393+ if (updating ) {
394+ Buffered_class = (PyObject * )state -> PyBufferedRandom_Type ;
395+ }
396+ else if (creating || writing || appending ) {
397+ Buffered_class = (PyObject * )state -> PyBufferedWriter_Type ;
398+ }
399+ else if (reading ) {
400+ Buffered_class = (PyObject * )state -> PyBufferedReader_Type ;
401+ }
399402 else {
400403 PyErr_Format (PyExc_ValueError ,
401404 "unknown mode: '%s'" , mode );
@@ -417,7 +420,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
417420 }
418421
419422 /* wraps into a TextIOWrapper */
420- wrapper = PyObject_CallFunction ((PyObject * )& PyTextIOWrapper_Type ,
423+ wrapper = PyObject_CallFunction ((PyObject * )state -> PyTextIOWrapper_Type ,
421424 "OsssO" ,
422425 buffer ,
423426 encoding , errors , newline ,
@@ -558,14 +561,6 @@ PyNumber_AsOff_t(PyObject *item, PyObject *err)
558561 return result ;
559562}
560563
561- static inline _PyIO_State *
562- get_io_state (PyObject * module )
563- {
564- void * state = _PyModule_GetState (module );
565- assert (state != NULL );
566- return (_PyIO_State * )state ;
567- }
568-
569564_PyIO_State *
570565_PyIO_get_module_state (void )
571566{
@@ -587,6 +582,15 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
587582 return 0 ;
588583 Py_VISIT (state -> locale_module );
589584 Py_VISIT (state -> unsupported_operation );
585+
586+ Py_VISIT (state -> PyBufferedRWPair_Type );
587+ Py_VISIT (state -> PyBufferedRandom_Type );
588+ Py_VISIT (state -> PyBufferedReader_Type );
589+ Py_VISIT (state -> PyBufferedWriter_Type );
590+ Py_VISIT (state -> PyBytesIO_Type );
591+ Py_VISIT (state -> PyFileIO_Type );
592+ Py_VISIT (state -> PyStringIO_Type );
593+ Py_VISIT (state -> PyTextIOWrapper_Type );
590594 return 0 ;
591595}
592596
@@ -599,6 +603,15 @@ iomodule_clear(PyObject *mod) {
599603 if (state -> locale_module != NULL )
600604 Py_CLEAR (state -> locale_module );
601605 Py_CLEAR (state -> unsupported_operation );
606+
607+ Py_CLEAR (state -> PyBufferedRWPair_Type );
608+ Py_CLEAR (state -> PyBufferedRandom_Type );
609+ Py_CLEAR (state -> PyBufferedReader_Type );
610+ Py_CLEAR (state -> PyBufferedWriter_Type );
611+ Py_CLEAR (state -> PyBytesIO_Type );
612+ Py_CLEAR (state -> PyFileIO_Type );
613+ Py_CLEAR (state -> PyStringIO_Type );
614+ Py_CLEAR (state -> PyTextIOWrapper_Type );
602615 return 0 ;
603616}
604617
@@ -612,7 +625,9 @@ iomodule_free(PyObject *mod) {
612625 * Module definition
613626 */
614627
628+ #define clinic_state () (get_io_state(module))
615629#include "clinic/_iomodule.c.h"
630+ #undef clinic_state
616631
617632static PyMethodDef module_methods [] = {
618633 _IO_OPEN_METHODDEF
@@ -644,23 +659,11 @@ static PyTypeObject* static_types[] = {
644659 & PyRawIOBase_Type ,
645660 & PyTextIOBase_Type ,
646661
647- // PyBufferedIOBase_Type(PyIOBase_Type) subclasses
648- & PyBytesIO_Type ,
649- & PyBufferedReader_Type ,
650- & PyBufferedWriter_Type ,
651- & PyBufferedRWPair_Type ,
652- & PyBufferedRandom_Type ,
653-
654662 // PyRawIOBase_Type(PyIOBase_Type) subclasses
655- & PyFileIO_Type ,
656663 & _PyBytesIOBuffer_Type ,
657664#ifdef MS_WINDOWS
658665 & PyWindowsConsoleIO_Type ,
659666#endif
660-
661- // PyTextIOBase_Type(PyIOBase_Type) subclasses
662- & PyStringIO_Type ,
663- & PyTextIOWrapper_Type ,
664667};
665668
666669
@@ -673,6 +676,17 @@ _PyIO_Fini(void)
673676 }
674677}
675678
679+ #define ADD_TYPE (module , type , spec , base ) \
680+ do { \
681+ type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \
682+ (PyObject *)base); \
683+ if (type == NULL) { \
684+ goto fail; \
685+ } \
686+ if (PyModule_AddType(module, type) < 0) { \
687+ goto fail; \
688+ } \
689+ } while (0)
676690
677691PyMODINIT_FUNC
678692PyInit__io (void )
@@ -705,17 +719,9 @@ PyInit__io(void)
705719 }
706720
707721 // Set type base classes
708- PyFileIO_Type .tp_base = & PyRawIOBase_Type ;
709- PyBytesIO_Type .tp_base = & PyBufferedIOBase_Type ;
710- PyStringIO_Type .tp_base = & PyTextIOBase_Type ;
711722#ifdef MS_WINDOWS
712723 PyWindowsConsoleIO_Type .tp_base = & PyRawIOBase_Type ;
713724#endif
714- PyBufferedReader_Type .tp_base = & PyBufferedIOBase_Type ;
715- PyBufferedWriter_Type .tp_base = & PyBufferedIOBase_Type ;
716- PyBufferedRWPair_Type .tp_base = & PyBufferedIOBase_Type ;
717- PyBufferedRandom_Type .tp_base = & PyBufferedIOBase_Type ;
718- PyTextIOWrapper_Type .tp_base = & PyTextIOBase_Type ;
719725
720726 // Add types
721727 for (size_t i = 0 ; i < Py_ARRAY_LENGTH (static_types ); i ++ ) {
@@ -725,6 +731,25 @@ PyInit__io(void)
725731 }
726732 }
727733
734+ // PyBufferedIOBase_Type(PyIOBase_Type) subclasses
735+ ADD_TYPE (m , state -> PyBytesIO_Type , & bytesio_spec , & PyBufferedIOBase_Type );
736+ ADD_TYPE (m , state -> PyBufferedWriter_Type , & bufferedwriter_spec ,
737+ & PyBufferedIOBase_Type );
738+ ADD_TYPE (m , state -> PyBufferedReader_Type , & bufferedreader_spec ,
739+ & PyBufferedIOBase_Type );
740+ ADD_TYPE (m , state -> PyBufferedRWPair_Type , & bufferedrwpair_spec ,
741+ & PyBufferedIOBase_Type );
742+ ADD_TYPE (m , state -> PyBufferedRandom_Type , & bufferedrandom_spec ,
743+ & PyBufferedIOBase_Type );
744+
745+ // PyRawIOBase_Type(PyIOBase_Type) subclasses
746+ ADD_TYPE (m , state -> PyFileIO_Type , & fileio_spec , & PyRawIOBase_Type );
747+
748+ // PyTextIOBase_Type(PyIOBase_Type) subclasses
749+ ADD_TYPE (m , state -> PyStringIO_Type , & stringio_spec , & PyTextIOBase_Type );
750+ ADD_TYPE (m , state -> PyTextIOWrapper_Type , & textiowrapper_spec ,
751+ & PyTextIOBase_Type );
752+
728753 state -> initialized = 1 ;
729754
730755 return m ;
0 commit comments