@@ -666,6 +666,82 @@ struct PyModuleDef _PyIO_Module = {
666666 (freefunc )iomodule_free ,
667667};
668668
669+
670+ static PyTypeObject * static_types [] = {
671+ // Base classes
672+ & PyIOBase_Type ,
673+ & PyIncrementalNewlineDecoder_Type ,
674+
675+ // PyIOBase_Type subclasses
676+ & PyBufferedIOBase_Type ,
677+ & PyRawIOBase_Type ,
678+ & PyTextIOBase_Type ,
679+
680+ // PyBufferedIOBase_Type(PyIOBase_Type) subclasses
681+ & PyBytesIO_Type ,
682+ & PyBufferedReader_Type ,
683+ & PyBufferedWriter_Type ,
684+ & PyBufferedRWPair_Type ,
685+ & PyBufferedRandom_Type ,
686+
687+ // PyRawIOBase_Type(PyIOBase_Type) subclasses
688+ & PyFileIO_Type ,
689+ & _PyBytesIOBuffer_Type ,
690+ #ifdef MS_WINDOWS
691+ & PyWindowsConsoleIO_Type ,
692+ #endif
693+
694+ // PyTextIOBase_Type(PyIOBase_Type) subclasses
695+ & PyStringIO_Type ,
696+ & PyTextIOWrapper_Type ,
697+ };
698+
699+
700+ void
701+ _PyIO_Fini (void )
702+ {
703+ for (Py_ssize_t i = Py_ARRAY_LENGTH (static_types ) - 1 ; i >= 0 ; i -- ) {
704+ PyTypeObject * exc = static_types [i ];
705+ _PyStaticType_Dealloc (exc );
706+ }
707+
708+ /* Interned strings */
709+ #define CLEAR_INTERNED (name ) \
710+ Py_CLEAR(_PyIO_str_ ## name)
711+
712+ CLEAR_INTERNED (close );
713+ CLEAR_INTERNED (closed );
714+ CLEAR_INTERNED (decode );
715+ CLEAR_INTERNED (encode );
716+ CLEAR_INTERNED (fileno );
717+ CLEAR_INTERNED (flush );
718+ CLEAR_INTERNED (getstate );
719+ CLEAR_INTERNED (isatty );
720+ CLEAR_INTERNED (locale );
721+ CLEAR_INTERNED (newlines );
722+ CLEAR_INTERNED (peek );
723+ CLEAR_INTERNED (read );
724+ CLEAR_INTERNED (read1 );
725+ CLEAR_INTERNED (readable );
726+ CLEAR_INTERNED (readall );
727+ CLEAR_INTERNED (readinto );
728+ CLEAR_INTERNED (readline );
729+ CLEAR_INTERNED (reset );
730+ CLEAR_INTERNED (seek );
731+ CLEAR_INTERNED (seekable );
732+ CLEAR_INTERNED (setstate );
733+ CLEAR_INTERNED (tell );
734+ CLEAR_INTERNED (truncate );
735+ CLEAR_INTERNED (write );
736+ CLEAR_INTERNED (writable );
737+ #undef CLEAR_INTERNED
738+
739+ Py_CLEAR (_PyIO_str_nl );
740+ Py_CLEAR (_PyIO_empty_str );
741+ Py_CLEAR (_PyIO_empty_bytes );
742+ }
743+
744+
669745PyMODINIT_FUNC
670746PyInit__io (void )
671747{
@@ -676,11 +752,6 @@ PyInit__io(void)
676752 state = get_io_state (m );
677753 state -> initialized = 0 ;
678754
679- #define ADD_TYPE (type ) \
680- if (PyModule_AddType(m, type) < 0) { \
681- goto fail; \
682- }
683-
684755 /* DEFAULT_BUFFER_SIZE */
685756 if (PyModule_AddIntMacro (m , DEFAULT_BUFFER_SIZE ) < 0 )
686757 goto fail ;
@@ -702,57 +773,34 @@ PyInit__io(void)
702773 (PyObject * ) PyExc_BlockingIOError ) < 0 )
703774 goto fail ;
704775
705- /* Concrete base types of the IO ABCs.
706- (the ABCs themselves are declared through inheritance in io.py)
707- */
708- ADD_TYPE (& PyIOBase_Type );
709- ADD_TYPE (& PyRawIOBase_Type );
710- ADD_TYPE (& PyBufferedIOBase_Type );
711- ADD_TYPE (& PyTextIOBase_Type );
712-
713- /* Implementation of concrete IO objects. */
714- /* FileIO */
776+ // Set type base classes
715777 PyFileIO_Type .tp_base = & PyRawIOBase_Type ;
716- ADD_TYPE (& PyFileIO_Type );
717-
718- /* BytesIO */
719778 PyBytesIO_Type .tp_base = & PyBufferedIOBase_Type ;
720- ADD_TYPE (& PyBytesIO_Type );
721- if (PyType_Ready (& _PyBytesIOBuffer_Type ) < 0 )
722- goto fail ;
723-
724- /* StringIO */
725779 PyStringIO_Type .tp_base = & PyTextIOBase_Type ;
726- ADD_TYPE (& PyStringIO_Type );
727-
728780#ifdef MS_WINDOWS
729- /* WindowsConsoleIO */
730781 PyWindowsConsoleIO_Type .tp_base = & PyRawIOBase_Type ;
731- ADD_TYPE (& PyWindowsConsoleIO_Type );
732782#endif
733-
734- /* BufferedReader */
735783 PyBufferedReader_Type .tp_base = & PyBufferedIOBase_Type ;
736- ADD_TYPE (& PyBufferedReader_Type );
737-
738- /* BufferedWriter */
739784 PyBufferedWriter_Type .tp_base = & PyBufferedIOBase_Type ;
740- ADD_TYPE (& PyBufferedWriter_Type );
741-
742- /* BufferedRWPair */
743785 PyBufferedRWPair_Type .tp_base = & PyBufferedIOBase_Type ;
744- ADD_TYPE (& PyBufferedRWPair_Type );
745-
746- /* BufferedRandom */
747786 PyBufferedRandom_Type .tp_base = & PyBufferedIOBase_Type ;
748- ADD_TYPE (& PyBufferedRandom_Type );
749-
750- /* TextIOWrapper */
751787 PyTextIOWrapper_Type .tp_base = & PyTextIOBase_Type ;
752- ADD_TYPE (& PyTextIOWrapper_Type );
753788
754- /* IncrementalNewlineDecoder */
755- ADD_TYPE (& PyIncrementalNewlineDecoder_Type );
789+ // Add types
790+ for (size_t i = 0 ; i < Py_ARRAY_LENGTH (static_types ); i ++ ) {
791+ PyTypeObject * type = static_types [i ];
792+ // Private type not exposed in the _io module
793+ if (type == & _PyBytesIOBuffer_Type ) {
794+ if (PyType_Ready (type ) < 0 ) {
795+ goto fail ;
796+ }
797+ }
798+ else {
799+ if (PyModule_AddType (m , type ) < 0 ) {
800+ goto fail ;
801+ }
802+ }
803+ }
756804
757805 /* Interned strings */
758806#define ADD_INTERNED (name ) \
@@ -785,6 +833,7 @@ PyInit__io(void)
785833 ADD_INTERNED (truncate )
786834 ADD_INTERNED (write )
787835 ADD_INTERNED (writable )
836+ #undef ADD_INTERNED
788837
789838 if (!_PyIO_str_nl &&
790839 !(_PyIO_str_nl = PyUnicode_InternFromString ("\n ")))
0 commit comments