Coverage Report

Created: 2026-04-12 06:54

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