xref: /third_party/python/Modules/_io/_iomodule.c (revision 7db96d56)
1/*
2    An implementation of the new I/O lib as defined by PEP 3116 - "New I/O"
3
4    Classes defined here: UnsupportedOperation, BlockingIOError.
5    Functions defined here: open().
6
7    Mostly written by Amaury Forgeot d'Arc
8*/
9
10#define PY_SSIZE_T_CLEAN
11#include "Python.h"
12#include "_iomodule.h"
13#include "pycore_pystate.h"       // _PyInterpreterState_GET()
14
15#ifdef HAVE_SYS_TYPES_H
16#include <sys/types.h>
17#endif /* HAVE_SYS_TYPES_H */
18
19#ifdef HAVE_SYS_STAT_H
20#include <sys/stat.h>
21#endif /* HAVE_SYS_STAT_H */
22
23#ifdef MS_WINDOWS
24#include <windows.h>
25#endif
26
27PyDoc_STRVAR(module_doc,
28"The io module provides the Python interfaces to stream handling. The\n"
29"builtin open function is defined in this module.\n"
30"\n"
31"At the top of the I/O hierarchy is the abstract base class IOBase. It\n"
32"defines the basic interface to a stream. Note, however, that there is no\n"
33"separation between reading and writing to streams; implementations are\n"
34"allowed to raise an OSError if they do not support a given operation.\n"
35"\n"
36"Extending IOBase is RawIOBase which deals simply with the reading and\n"
37"writing of raw bytes to a stream. FileIO subclasses RawIOBase to provide\n"
38"an interface to OS files.\n"
39"\n"
40"BufferedIOBase deals with buffering on a raw byte stream (RawIOBase). Its\n"
41"subclasses, BufferedWriter, BufferedReader, and BufferedRWPair buffer\n"
42"streams that are readable, writable, and both respectively.\n"
43"BufferedRandom provides a buffered interface to random access\n"
44"streams. BytesIO is a simple stream of in-memory bytes.\n"
45"\n"
46"Another IOBase subclass, TextIOBase, deals with the encoding and decoding\n"
47"of streams into text. TextIOWrapper, which extends it, is a buffered text\n"
48"interface to a buffered raw stream (`BufferedIOBase`). Finally, StringIO\n"
49"is an in-memory stream for text.\n"
50"\n"
51"Argument names are not part of the specification, and only the arguments\n"
52"of open() are intended to be used as keyword arguments.\n"
53"\n"
54"data:\n"
55"\n"
56"DEFAULT_BUFFER_SIZE\n"
57"\n"
58"   An int containing the default buffer size used by the module's buffered\n"
59"   I/O classes. open() uses the file's blksize (as obtained by os.stat) if\n"
60"   possible.\n"
61    );
62
63
64/*
65 * The main open() function
66 */
67/*[clinic input]
68module _io
69
70_io.open
71    file: object
72    mode: str = "r"
73    buffering: int = -1
74    encoding: str(accept={str, NoneType}) = None
75    errors: str(accept={str, NoneType}) = None
76    newline: str(accept={str, NoneType}) = None
77    closefd: bool(accept={int}) = True
78    opener: object = None
79
80Open file and return a stream.  Raise OSError upon failure.
81
82file is either a text or byte string giving the name (and the path
83if the file isn't in the current working directory) of the file to
84be opened or an integer file descriptor of the file to be
85wrapped. (If a file descriptor is given, it is closed when the
86returned I/O object is closed, unless closefd is set to False.)
87
88mode is an optional string that specifies the mode in which the file
89is opened. It defaults to 'r' which means open for reading in text
90mode.  Other common values are 'w' for writing (truncating the file if
91it already exists), 'x' for creating and writing to a new file, and
92'a' for appending (which on some Unix systems, means that all writes
93append to the end of the file regardless of the current seek position).
94In text mode, if encoding is not specified the encoding used is platform
95dependent: locale.getencoding() is called to get the current locale encoding.
96(For reading and writing raw bytes use binary mode and leave encoding
97unspecified.) The available modes are:
98
99========= ===============================================================
100Character Meaning
101--------- ---------------------------------------------------------------
102'r'       open for reading (default)
103'w'       open for writing, truncating the file first
104'x'       create a new file and open it for writing
105'a'       open for writing, appending to the end of the file if it exists
106'b'       binary mode
107't'       text mode (default)
108'+'       open a disk file for updating (reading and writing)
109========= ===============================================================
110
111The default mode is 'rt' (open for reading text). For binary random
112access, the mode 'w+b' opens and truncates the file to 0 bytes, while
113'r+b' opens the file without truncation. The 'x' mode implies 'w' and
114raises an `FileExistsError` if the file already exists.
115
116Python distinguishes between files opened in binary and text modes,
117even when the underlying operating system doesn't. Files opened in
118binary mode (appending 'b' to the mode argument) return contents as
119bytes objects without any decoding. In text mode (the default, or when
120't' is appended to the mode argument), the contents of the file are
121returned as strings, the bytes having been first decoded using a
122platform-dependent encoding or using the specified encoding if given.
123
124buffering is an optional integer used to set the buffering policy.
125Pass 0 to switch buffering off (only allowed in binary mode), 1 to select
126line buffering (only usable in text mode), and an integer > 1 to indicate
127the size of a fixed-size chunk buffer.  When no buffering argument is
128given, the default buffering policy works as follows:
129
130* Binary files are buffered in fixed-size chunks; the size of the buffer
131  is chosen using a heuristic trying to determine the underlying device's
132  "block size" and falling back on `io.DEFAULT_BUFFER_SIZE`.
133  On many systems, the buffer will typically be 4096 or 8192 bytes long.
134
135* "Interactive" text files (files for which isatty() returns True)
136  use line buffering.  Other text files use the policy described above
137  for binary files.
138
139encoding is the name of the encoding used to decode or encode the
140file. This should only be used in text mode. The default encoding is
141platform dependent, but any encoding supported by Python can be
142passed.  See the codecs module for the list of supported encodings.
143
144errors is an optional string that specifies how encoding errors are to
145be handled---this argument should not be used in binary mode. Pass
146'strict' to raise a ValueError exception if there is an encoding error
147(the default of None has the same effect), or pass 'ignore' to ignore
148errors. (Note that ignoring encoding errors can lead to data loss.)
149See the documentation for codecs.register or run 'help(codecs.Codec)'
150for a list of the permitted encoding error strings.
151
152newline controls how universal newlines works (it only applies to text
153mode). It can be None, '', '\n', '\r', and '\r\n'.  It works as
154follows:
155
156* On input, if newline is None, universal newlines mode is
157  enabled. Lines in the input can end in '\n', '\r', or '\r\n', and
158  these are translated into '\n' before being returned to the
159  caller. If it is '', universal newline mode is enabled, but line
160  endings are returned to the caller untranslated. If it has any of
161  the other legal values, input lines are only terminated by the given
162  string, and the line ending is returned to the caller untranslated.
163
164* On output, if newline is None, any '\n' characters written are
165  translated to the system default line separator, os.linesep. If
166  newline is '' or '\n', no translation takes place. If newline is any
167  of the other legal values, any '\n' characters written are translated
168  to the given string.
169
170If closefd is False, the underlying file descriptor will be kept open
171when the file is closed. This does not work when a file name is given
172and must be True in that case.
173
174A custom opener can be used by passing a callable as *opener*. The
175underlying file descriptor for the file object is then obtained by
176calling *opener* with (*file*, *flags*). *opener* must return an open
177file descriptor (passing os.open as *opener* results in functionality
178similar to passing None).
179
180open() returns a file object whose type depends on the mode, and
181through which the standard file operations such as reading and writing
182are performed. When open() is used to open a file in a text mode ('w',
183'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open
184a file in a binary mode, the returned class varies: in read binary
185mode, it returns a BufferedReader; in write binary and append binary
186modes, it returns a BufferedWriter, and in read/write mode, it returns
187a BufferedRandom.
188
189It is also possible to use a string or bytearray as a file for both
190reading and writing. For strings StringIO can be used like a file
191opened in a text mode, and for bytes a BytesIO can be used like a file
192opened in a binary mode.
193[clinic start generated code]*/
194
195static PyObject *
196_io_open_impl(PyObject *module, PyObject *file, const char *mode,
197              int buffering, const char *encoding, const char *errors,
198              const char *newline, int closefd, PyObject *opener)
199/*[clinic end generated code: output=aefafc4ce2b46dc0 input=5bb37f174cb2fb11]*/
200{
201    unsigned i;
202
203    int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0;
204    int text = 0, binary = 0;
205
206    char rawmode[6], *m;
207    int line_buffering, is_number;
208    long isatty = 0;
209
210    PyObject *raw, *modeobj = NULL, *buffer, *wrapper, *result = NULL, *path_or_fd = NULL;
211
212    is_number = PyNumber_Check(file);
213
214    if (is_number) {
215        path_or_fd = file;
216        Py_INCREF(path_or_fd);
217    } else {
218        path_or_fd = PyOS_FSPath(file);
219        if (path_or_fd == NULL) {
220            return NULL;
221        }
222    }
223
224    if (!is_number &&
225        !PyUnicode_Check(path_or_fd) &&
226        !PyBytes_Check(path_or_fd)) {
227        PyErr_Format(PyExc_TypeError, "invalid file: %R", file);
228        goto error;
229    }
230
231    /* Decode mode */
232    for (i = 0; i < strlen(mode); i++) {
233        char c = mode[i];
234
235        switch (c) {
236        case 'x':
237            creating = 1;
238            break;
239        case 'r':
240            reading = 1;
241            break;
242        case 'w':
243            writing = 1;
244            break;
245        case 'a':
246            appending = 1;
247            break;
248        case '+':
249            updating = 1;
250            break;
251        case 't':
252            text = 1;
253            break;
254        case 'b':
255            binary = 1;
256            break;
257        default:
258            goto invalid_mode;
259        }
260
261        /* c must not be duplicated */
262        if (strchr(mode+i+1, c)) {
263          invalid_mode:
264            PyErr_Format(PyExc_ValueError, "invalid mode: '%s'", mode);
265            goto error;
266        }
267
268    }
269
270    m = rawmode;
271    if (creating)  *(m++) = 'x';
272    if (reading)   *(m++) = 'r';
273    if (writing)   *(m++) = 'w';
274    if (appending) *(m++) = 'a';
275    if (updating)  *(m++) = '+';
276    *m = '\0';
277
278    /* Parameters validation */
279    if (text && binary) {
280        PyErr_SetString(PyExc_ValueError,
281                        "can't have text and binary mode at once");
282        goto error;
283    }
284
285    if (creating + reading + writing + appending > 1) {
286        PyErr_SetString(PyExc_ValueError,
287                        "must have exactly one of create/read/write/append mode");
288        goto error;
289    }
290
291    if (binary && encoding != NULL) {
292        PyErr_SetString(PyExc_ValueError,
293                        "binary mode doesn't take an encoding argument");
294        goto error;
295    }
296
297    if (binary && errors != NULL) {
298        PyErr_SetString(PyExc_ValueError,
299                        "binary mode doesn't take an errors argument");
300        goto error;
301    }
302
303    if (binary && newline != NULL) {
304        PyErr_SetString(PyExc_ValueError,
305                        "binary mode doesn't take a newline argument");
306        goto error;
307    }
308
309    if (binary && buffering == 1) {
310        if (PyErr_WarnEx(PyExc_RuntimeWarning,
311                         "line buffering (buffering=1) isn't supported in "
312                         "binary mode, the default buffer size will be used",
313                         1) < 0) {
314           goto error;
315        }
316    }
317
318    /* Create the Raw file stream */
319    {
320        PyObject *RawIO_class = (PyObject *)&PyFileIO_Type;
321#ifdef MS_WINDOWS
322        const PyConfig *config = _Py_GetConfig();
323        if (!config->legacy_windows_stdio && _PyIO_get_console_type(path_or_fd) != '\0') {
324            RawIO_class = (PyObject *)&PyWindowsConsoleIO_Type;
325            encoding = "utf-8";
326        }
327#endif
328        raw = PyObject_CallFunction(RawIO_class, "OsOO",
329                                    path_or_fd, rawmode,
330                                    closefd ? Py_True : Py_False,
331                                    opener);
332    }
333
334    if (raw == NULL)
335        goto error;
336    result = raw;
337
338    Py_DECREF(path_or_fd);
339    path_or_fd = NULL;
340
341    modeobj = PyUnicode_FromString(mode);
342    if (modeobj == NULL)
343        goto error;
344
345    /* buffering */
346    if (buffering < 0) {
347        PyObject *res = PyObject_CallMethodNoArgs(raw, &_Py_ID(isatty));
348        if (res == NULL)
349            goto error;
350        isatty = PyLong_AsLong(res);
351        Py_DECREF(res);
352        if (isatty == -1 && PyErr_Occurred())
353            goto error;
354    }
355
356    if (buffering == 1 || isatty) {
357        buffering = -1;
358        line_buffering = 1;
359    }
360    else
361        line_buffering = 0;
362
363    if (buffering < 0) {
364        PyObject *blksize_obj;
365        blksize_obj = PyObject_GetAttr(raw, &_Py_ID(_blksize));
366        if (blksize_obj == NULL)
367            goto error;
368        buffering = PyLong_AsLong(blksize_obj);
369        Py_DECREF(blksize_obj);
370        if (buffering == -1 && PyErr_Occurred())
371            goto error;
372    }
373    if (buffering < 0) {
374        PyErr_SetString(PyExc_ValueError,
375                        "invalid buffering size");
376        goto error;
377    }
378
379    /* if not buffering, returns the raw file object */
380    if (buffering == 0) {
381        if (!binary) {
382            PyErr_SetString(PyExc_ValueError,
383                            "can't have unbuffered text I/O");
384            goto error;
385        }
386
387        Py_DECREF(modeobj);
388        return result;
389    }
390
391    /* wraps into a buffered file */
392    {
393        PyObject *Buffered_class;
394
395        if (updating)
396            Buffered_class = (PyObject *)&PyBufferedRandom_Type;
397        else if (creating || writing || appending)
398            Buffered_class = (PyObject *)&PyBufferedWriter_Type;
399        else if (reading)
400            Buffered_class = (PyObject *)&PyBufferedReader_Type;
401        else {
402            PyErr_Format(PyExc_ValueError,
403                         "unknown mode: '%s'", mode);
404            goto error;
405        }
406
407        buffer = PyObject_CallFunction(Buffered_class, "Oi", raw, buffering);
408    }
409    if (buffer == NULL)
410        goto error;
411    result = buffer;
412    Py_DECREF(raw);
413
414
415    /* if binary, returns the buffered file */
416    if (binary) {
417        Py_DECREF(modeobj);
418        return result;
419    }
420
421    /* wraps into a TextIOWrapper */
422    wrapper = PyObject_CallFunction((PyObject *)&PyTextIOWrapper_Type,
423                                    "OsssO",
424                                    buffer,
425                                    encoding, errors, newline,
426                                    line_buffering ? Py_True : Py_False);
427    if (wrapper == NULL)
428        goto error;
429    result = wrapper;
430    Py_DECREF(buffer);
431
432    if (PyObject_SetAttr(wrapper, &_Py_ID(mode), modeobj) < 0)
433        goto error;
434    Py_DECREF(modeobj);
435    return result;
436
437  error:
438    if (result != NULL) {
439        PyObject *exc, *val, *tb, *close_result;
440        PyErr_Fetch(&exc, &val, &tb);
441        close_result = PyObject_CallMethodNoArgs(result, &_Py_ID(close));
442        _PyErr_ChainExceptions(exc, val, tb);
443        Py_XDECREF(close_result);
444        Py_DECREF(result);
445    }
446    Py_XDECREF(path_or_fd);
447    Py_XDECREF(modeobj);
448    return NULL;
449}
450
451
452/*[clinic input]
453_io.text_encoding
454    encoding: object
455    stacklevel: int = 2
456    /
457
458A helper function to choose the text encoding.
459
460When encoding is not None, this function returns it.
461Otherwise, this function returns the default text encoding
462(i.e. "locale" or "utf-8" depends on UTF-8 mode).
463
464This function emits an EncodingWarning if encoding is None and
465sys.flags.warn_default_encoding is true.
466
467This can be used in APIs with an encoding=None parameter.
468However, please consider using encoding="utf-8" for new APIs.
469[clinic start generated code]*/
470
471static PyObject *
472_io_text_encoding_impl(PyObject *module, PyObject *encoding, int stacklevel)
473/*[clinic end generated code: output=91b2cfea6934cc0c input=4999aa8b3d90f3d4]*/
474{
475    if (encoding == NULL || encoding == Py_None) {
476        PyInterpreterState *interp = _PyInterpreterState_GET();
477        if (_PyInterpreterState_GetConfig(interp)->warn_default_encoding) {
478            if (PyErr_WarnEx(PyExc_EncodingWarning,
479                             "'encoding' argument not specified", stacklevel)) {
480                return NULL;
481            }
482        }
483        const PyPreConfig *preconfig = &_PyRuntime.preconfig;
484        if (preconfig->utf8_mode) {
485            _Py_DECLARE_STR(utf_8, "utf-8");
486            encoding = &_Py_STR(utf_8);
487        }
488        else {
489            encoding = &_Py_ID(locale);
490        }
491    }
492    Py_INCREF(encoding);
493    return encoding;
494}
495
496
497/*[clinic input]
498_io.open_code
499
500    path : unicode
501
502Opens the provided file with the intent to import the contents.
503
504This may perform extra validation beyond open(), but is otherwise interchangeable
505with calling open(path, 'rb').
506
507[clinic start generated code]*/
508
509static PyObject *
510_io_open_code_impl(PyObject *module, PyObject *path)
511/*[clinic end generated code: output=2fe4ecbd6f3d6844 input=f5c18e23f4b2ed9f]*/
512{
513    return PyFile_OpenCodeObject(path);
514}
515
516/*
517 * Private helpers for the io module.
518 */
519
520Py_off_t
521PyNumber_AsOff_t(PyObject *item, PyObject *err)
522{
523    Py_off_t result;
524    PyObject *runerr;
525    PyObject *value = _PyNumber_Index(item);
526    if (value == NULL)
527        return -1;
528
529    /* We're done if PyLong_AsSsize_t() returns without error. */
530    result = PyLong_AsOff_t(value);
531    if (result != -1 || !(runerr = PyErr_Occurred()))
532        goto finish;
533
534    /* Error handling code -- only manage OverflowError differently */
535    if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError))
536        goto finish;
537
538    PyErr_Clear();
539    /* If no error-handling desired then the default clipping
540       is sufficient.
541     */
542    if (!err) {
543        assert(PyLong_Check(value));
544        /* Whether or not it is less than or equal to
545           zero is determined by the sign of ob_size
546        */
547        if (_PyLong_Sign(value) < 0)
548            result = PY_OFF_T_MIN;
549        else
550            result = PY_OFF_T_MAX;
551    }
552    else {
553        /* Otherwise replace the error with caller's error object. */
554        PyErr_Format(err,
555                     "cannot fit '%.200s' into an offset-sized integer",
556                     Py_TYPE(item)->tp_name);
557    }
558
559 finish:
560    Py_DECREF(value);
561    return result;
562}
563
564static inline _PyIO_State*
565get_io_state(PyObject *module)
566{
567    void *state = PyModule_GetState(module);
568    assert(state != NULL);
569    return (_PyIO_State *)state;
570}
571
572_PyIO_State *
573_PyIO_get_module_state(void)
574{
575    PyObject *mod = PyState_FindModule(&_PyIO_Module);
576    _PyIO_State *state;
577    if (mod == NULL || (state = get_io_state(mod)) == NULL) {
578        PyErr_SetString(PyExc_RuntimeError,
579                        "could not find io module state "
580                        "(interpreter shutdown?)");
581        return NULL;
582    }
583    return state;
584}
585
586static int
587iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
588    _PyIO_State *state = get_io_state(mod);
589    if (!state->initialized)
590        return 0;
591    Py_VISIT(state->locale_module);
592    Py_VISIT(state->unsupported_operation);
593    return 0;
594}
595
596
597static int
598iomodule_clear(PyObject *mod) {
599    _PyIO_State *state = get_io_state(mod);
600    if (!state->initialized)
601        return 0;
602    if (state->locale_module != NULL)
603        Py_CLEAR(state->locale_module);
604    Py_CLEAR(state->unsupported_operation);
605    return 0;
606}
607
608static void
609iomodule_free(PyObject *mod) {
610    iomodule_clear(mod);
611}
612
613
614/*
615 * Module definition
616 */
617
618#include "clinic/_iomodule.c.h"
619
620static PyMethodDef module_methods[] = {
621    _IO_OPEN_METHODDEF
622    _IO_TEXT_ENCODING_METHODDEF
623    _IO_OPEN_CODE_METHODDEF
624    {NULL, NULL}
625};
626
627struct PyModuleDef _PyIO_Module = {
628    PyModuleDef_HEAD_INIT,
629    "io",
630    module_doc,
631    sizeof(_PyIO_State),
632    module_methods,
633    NULL,
634    iomodule_traverse,
635    iomodule_clear,
636    (freefunc)iomodule_free,
637};
638
639
640static PyTypeObject* static_types[] = {
641    // Base classes
642    &PyIOBase_Type,
643    &PyIncrementalNewlineDecoder_Type,
644
645    // PyIOBase_Type subclasses
646    &PyBufferedIOBase_Type,
647    &PyRawIOBase_Type,
648    &PyTextIOBase_Type,
649
650    // PyBufferedIOBase_Type(PyIOBase_Type) subclasses
651    &PyBytesIO_Type,
652    &PyBufferedReader_Type,
653    &PyBufferedWriter_Type,
654    &PyBufferedRWPair_Type,
655    &PyBufferedRandom_Type,
656
657    // PyRawIOBase_Type(PyIOBase_Type) subclasses
658    &PyFileIO_Type,
659    &_PyBytesIOBuffer_Type,
660#ifdef MS_WINDOWS
661    &PyWindowsConsoleIO_Type,
662#endif
663
664    // PyTextIOBase_Type(PyIOBase_Type) subclasses
665    &PyStringIO_Type,
666    &PyTextIOWrapper_Type,
667};
668
669
670void
671_PyIO_Fini(void)
672{
673    for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types) - 1; i >= 0; i--) {
674        PyTypeObject *exc = static_types[i];
675        _PyStaticType_Dealloc(exc);
676    }
677}
678
679
680PyMODINIT_FUNC
681PyInit__io(void)
682{
683    PyObject *m = PyModule_Create(&_PyIO_Module);
684    _PyIO_State *state = NULL;
685    if (m == NULL)
686        return NULL;
687    state = get_io_state(m);
688    state->initialized = 0;
689
690    /* DEFAULT_BUFFER_SIZE */
691    if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0)
692        goto fail;
693
694    /* UnsupportedOperation inherits from ValueError and OSError */
695    state->unsupported_operation = PyObject_CallFunction(
696        (PyObject *)&PyType_Type, "s(OO){}",
697        "UnsupportedOperation", PyExc_OSError, PyExc_ValueError);
698    if (state->unsupported_operation == NULL)
699        goto fail;
700    Py_INCREF(state->unsupported_operation);
701    if (PyModule_AddObject(m, "UnsupportedOperation",
702                           state->unsupported_operation) < 0)
703        goto fail;
704
705    /* BlockingIOError, for compatibility */
706    if (PyModule_AddObjectRef(m, "BlockingIOError",
707                              (PyObject *) PyExc_BlockingIOError) < 0) {
708        goto fail;
709    }
710
711    // Set type base classes
712    PyFileIO_Type.tp_base = &PyRawIOBase_Type;
713    PyBytesIO_Type.tp_base = &PyBufferedIOBase_Type;
714    PyStringIO_Type.tp_base = &PyTextIOBase_Type;
715#ifdef MS_WINDOWS
716    PyWindowsConsoleIO_Type.tp_base = &PyRawIOBase_Type;
717#endif
718    PyBufferedReader_Type.tp_base = &PyBufferedIOBase_Type;
719    PyBufferedWriter_Type.tp_base = &PyBufferedIOBase_Type;
720    PyBufferedRWPair_Type.tp_base = &PyBufferedIOBase_Type;
721    PyBufferedRandom_Type.tp_base = &PyBufferedIOBase_Type;
722    PyTextIOWrapper_Type.tp_base = &PyTextIOBase_Type;
723
724    // Add types
725    for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
726        PyTypeObject *type = static_types[i];
727        // Private type not exposed in the _io module
728        if (type == &_PyBytesIOBuffer_Type) {
729            if (PyType_Ready(type) < 0) {
730                goto fail;
731            }
732        }
733        else {
734            if (PyModule_AddType(m, type) < 0) {
735                goto fail;
736            }
737        }
738    }
739
740    state->initialized = 1;
741
742    return m;
743
744  fail:
745    Py_XDECREF(state->unsupported_operation);
746    Py_DECREF(m);
747    return NULL;
748}
749