Coverage Report

Created: 2026-09-27 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython3/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
_io.open
74
    file: object
75
    mode: str = "r"
76
    buffering: int = -1
77
    encoding: str(accept={str, NoneType}) = None
78
    errors: str(accept={str, NoneType}) = None
79
    newline: str(accept={str, NoneType}) = None
80
    closefd: bool = True
81
    opener: object = None
82
83
Open file and return a stream.  Raise OSError upon failure.
84
85
file is either a text or byte string giving the name (and the path
86
if the file isn't in the current working directory) of the file to
87
be opened or an integer file descriptor of the file to be
88
wrapped.  (If a file descriptor is given, it is closed when the
89
returned I/O object is closed, unless closefd is set to False.)
90
91
mode is an optional string that specifies the mode in which the file
92
is opened.  It defaults to 'r' which means open for reading in text
93
mode.  Other common values are 'w' for writing (truncating the file if
94
it already exists), 'x' for creating and writing to a new file, and
95
'a' for appending (which on some Unix systems, means that all writes
96
append to the end of the file regardless of the current seek position).
97
In text mode, if encoding is not specified the encoding used is platform
98
dependent: locale.getencoding() is called to get the current locale
99
encoding.  (For reading and writing raw bytes use binary mode and leave
100
encoding unspecified.)  The available modes are:
101
102
========= ==========================================================
103
Character Meaning
104
--------- ----------------------------------------------------------
105
'r'       open for reading (default)
106
'w'       open for writing, truncating the file first
107
'x'       create a new file and open it for writing
108
'a'       open for writing, appending to the end of the file if it
109
          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
130
select line buffering (only usable in text mode), and an integer > 1 to
131
indicate the size of a fixed-size chunk buffer.   When no buffering
132
argument is 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) when the device
136
  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 enabled.
161
  Lines in the input can end in '\n', '\r', or '\r\n', and these are
162
  translated into '\n' before being returned to the caller.  If it is
163
  '', universal newline mode is enabled, but line endings are returned
164
  to the caller untranslated.  If it has any of the other legal values,
165
  input lines are only terminated by the given string, and the line
166
  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=b3cefa70bef404b3]*/
204
341
{
205
341
    size_t i;
206
207
341
    int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0;
208
341
    int text = 0, binary = 0;
209
210
341
    char rawmode[6], *m;
211
341
    int line_buffering, is_number, isatty = 0;
212
213
341
    PyObject *raw, *modeobj = NULL, *buffer, *wrapper, *result = NULL, *path_or_fd = NULL;
214
215
341
    is_number = PyNumber_Check(file);
216
217
341
    if (is_number) {
218
63
        path_or_fd = Py_NewRef(file);
219
278
    } else {
220
278
        path_or_fd = PyOS_FSPath(file);
221
278
        if (path_or_fd == NULL) {
222
0
            return NULL;
223
0
        }
224
278
    }
225
226
341
    if (!is_number &&
227
341
        !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
1.02k
    for (i = 0; i < strlen(mode); i++) {
235
682
        char c = mode[i];
236
237
682
        switch (c) {
238
0
        case 'x':
239
0
            creating = 1;
240
0
            break;
241
299
        case 'r':
242
299
            reading = 1;
243
299
            break;
244
42
        case 'w':
245
42
            writing = 1;
246
42
            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
341
        case 'b':
257
341
            binary = 1;
258
341
            break;
259
0
        default:
260
0
            goto invalid_mode;
261
682
        }
262
263
        /* c must not be duplicated */
264
682
        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
682
    }
271
272
341
    m = rawmode;
273
341
    if (creating)  *(m++) = 'x';
274
341
    if (reading)   *(m++) = 'r';
275
341
    if (writing)   *(m++) = 'w';
276
341
    if (appending) *(m++) = 'a';
277
341
    if (updating)  *(m++) = '+';
278
341
    *m = '\0';
279
280
    /* Parameters validation */
281
341
    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
341
    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
341
    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
341
    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
341
    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
341
    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
341
    _PyIO_State *state = get_io_state(module);
322
341
    {
323
341
        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
341
        raw = PyObject_CallFunction(RawIO_class, "OsOO",
332
341
                                    path_or_fd, rawmode,
333
341
                                    closefd ? Py_True : Py_False,
334
341
                                    opener);
335
341
    }
336
337
341
    if (raw == NULL)
338
0
        goto error;
339
341
    result = raw;
340
341
341
    Py_SETREF(path_or_fd, NULL);
342
343
341
    modeobj = PyUnicode_FromString(mode);
344
341
    if (modeobj == NULL)
345
0
        goto error;
346
347
    /* buffering */
348
341
    if (buffering < 0) {
349
341
        PyObject *res = PyObject_CallMethodNoArgs(raw, &_Py_ID(_isatty_open_only));
350
341
        if (res == NULL)
351
0
            goto error;
352
341
        isatty = PyObject_IsTrue(res);
353
341
        Py_DECREF(res);
354
341
        if (isatty < 0)
355
0
            goto error;
356
341
    }
357
358
341
    if (buffering == 1 || isatty) {
359
0
        buffering = -1;
360
0
        line_buffering = 1;
361
0
    }
362
341
    else
363
341
        line_buffering = 0;
364
365
341
    if (buffering < 0) {
366
341
        PyObject *blksize_obj;
367
341
        blksize_obj = PyObject_GetAttr(raw, &_Py_ID(_blksize));
368
341
        if (blksize_obj == NULL)
369
0
            goto error;
370
341
        buffering = PyLong_AsLong(blksize_obj);
371
341
        Py_DECREF(blksize_obj);
372
341
        if (buffering == -1 && PyErr_Occurred())
373
0
            goto error;
374
341
        buffering = Py_MAX(Py_MIN(buffering, 8192 * 1024), DEFAULT_BUFFER_SIZE);
375
341
    }
376
341
    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
341
    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
341
    {
396
341
        PyObject *Buffered_class;
397
398
341
        if (updating) {
399
0
            Buffered_class = (PyObject *)state->PyBufferedRandom_Type;
400
0
        }
401
341
        else if (creating || writing || appending) {
402
42
            Buffered_class = (PyObject *)state->PyBufferedWriter_Type;
403
42
        }
404
299
        else if (reading) {
405
299
            Buffered_class = (PyObject *)state->PyBufferedReader_Type;
406
299
        }
407
0
        else {
408
0
            PyErr_Format(PyExc_ValueError,
409
0
                         "unknown mode: '%s'", mode);
410
0
            goto error;
411
0
        }
412
413
341
        buffer = PyObject_CallFunction(Buffered_class, "Oi", raw, buffering);
414
341
    }
415
341
    if (buffer == NULL)
416
0
        goto error;
417
341
    result = buffer;
418
341
    Py_DECREF(raw);
419
420
421
    /* if binary, returns the buffered file */
422
341
    if (binary) {
423
341
        Py_DECREF(modeobj);
424
341
        return result;
425
341
    }
426
427
    /* wraps into a TextIOWrapper */
428
0
    wrapper = PyObject_CallFunction((PyObject *)state->PyTextIOWrapper_Type,
429
0
                                    "OsssO",
430
0
                                    buffer,
431
0
                                    encoding, errors, newline,
432
0
                                    line_buffering ? Py_True : Py_False);
433
0
    if (wrapper == NULL)
434
0
        goto error;
435
0
    result = wrapper;
436
0
    Py_DECREF(buffer);
437
438
0
    if (PyObject_SetAttr(wrapper, &_Py_ID(mode), modeobj) < 0)
439
0
        goto error;
440
0
    Py_DECREF(modeobj);
441
0
    return result;
442
443
0
  error:
444
0
    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
0
    Py_XDECREF(path_or_fd);
452
0
    Py_XDECREF(modeobj);
453
0
    return NULL;
454
0
}
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
0
{
480
0
    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
0
    return Py_NewRef(encoding);
498
0
}
499
500
501
/*[clinic input]
502
_io.open_code
503
504
    path : unicode
505
506
Opens the provided file with the intent to import the contents.
507
508
This may perform extra validation beyond open(), but is otherwise
509
interchangeable with calling open(path, 'rb').
510
511
[clinic start generated code]*/
512
513
static PyObject *
514
_io_open_code_impl(PyObject *module, PyObject *path)
515
/*[clinic end generated code: output=2fe4ecbd6f3d6844 input=2803c35aeb63c719]*/
516
278
{
517
278
    return PyFile_OpenCodeObject(path);
518
278
}
519
520
/*
521
 * Private helpers for the io module.
522
 */
523
524
Py_off_t
525
PyNumber_AsOff_t(PyObject *item, PyObject *err)
526
383
{
527
383
    Py_off_t result;
528
383
    PyObject *runerr;
529
383
    PyObject *value = _PyNumber_Index(item);
530
383
    if (value == NULL)
531
0
        return -1;
532
533
    /* We're done if PyLong_AsSsize_t() returns without error. */
534
383
    result = PyLong_AsOff_t(value);
535
383
    if (result != -1 || !(runerr = PyErr_Occurred()))
536
383
        goto finish;
537
538
    /* Error handling code -- only manage OverflowError differently */
539
0
    if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError))
540
0
        goto finish;
541
542
0
    PyErr_Clear();
543
    /* If no error-handling desired then the default clipping
544
       is sufficient.
545
     */
546
0
    if (!err) {
547
0
        assert(PyLong_Check(value));
548
0
        if (_PyLong_IsNegative((PyLongObject *)value))
549
0
            result = PY_OFF_T_MIN;
550
0
        else
551
0
            result = PY_OFF_T_MAX;
552
0
    }
553
0
    else {
554
        /* Otherwise replace the error with caller's error object. */
555
0
        PyErr_Format(err,
556
0
                     "cannot fit '%.200s' into an offset-sized integer",
557
0
                     Py_TYPE(item)->tp_name);
558
0
    }
559
560
383
 finish:
561
383
    Py_DECREF(value);
562
383
    return result;
563
0
}
564
565
static int
566
392
iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
567
392
    _PyIO_State *state = get_io_state(mod);
568
392
    Py_VISIT(state->unsupported_operation);
569
570
392
    Py_VISIT(state->PyIOBase_Type);
571
392
    Py_VISIT(state->PyIncrementalNewlineDecoder_Type);
572
392
    Py_VISIT(state->PyRawIOBase_Type);
573
392
    Py_VISIT(state->PyBufferedIOBase_Type);
574
392
    Py_VISIT(state->PyBufferedRWPair_Type);
575
392
    Py_VISIT(state->PyBufferedRandom_Type);
576
392
    Py_VISIT(state->PyBufferedReader_Type);
577
392
    Py_VISIT(state->PyBufferedWriter_Type);
578
392
    Py_VISIT(state->PyBytesIOBuffer_Type);
579
392
    Py_VISIT(state->PyBytesIO_Type);
580
392
    Py_VISIT(state->PyFileIO_Type);
581
392
    Py_VISIT(state->PyStringIO_Type);
582
392
    Py_VISIT(state->PyTextIOBase_Type);
583
392
    Py_VISIT(state->PyTextIOWrapper_Type);
584
#ifdef HAVE_WINDOWS_CONSOLE_IO
585
    Py_VISIT(state->PyWindowsConsoleIO_Type);
586
#endif
587
392
    return 0;
588
392
}
589
590
591
static int
592
0
iomodule_clear(PyObject *mod) {
593
0
    _PyIO_State *state = get_io_state(mod);
594
0
    Py_CLEAR(state->unsupported_operation);
595
596
0
    Py_CLEAR(state->PyIOBase_Type);
597
0
    Py_CLEAR(state->PyIncrementalNewlineDecoder_Type);
598
0
    Py_CLEAR(state->PyRawIOBase_Type);
599
0
    Py_CLEAR(state->PyBufferedIOBase_Type);
600
0
    Py_CLEAR(state->PyBufferedRWPair_Type);
601
0
    Py_CLEAR(state->PyBufferedRandom_Type);
602
0
    Py_CLEAR(state->PyBufferedReader_Type);
603
0
    Py_CLEAR(state->PyBufferedWriter_Type);
604
0
    Py_CLEAR(state->PyBytesIOBuffer_Type);
605
0
    Py_CLEAR(state->PyBytesIO_Type);
606
0
    Py_CLEAR(state->PyFileIO_Type);
607
0
    Py_CLEAR(state->PyStringIO_Type);
608
0
    Py_CLEAR(state->PyTextIOBase_Type);
609
0
    Py_CLEAR(state->PyTextIOWrapper_Type);
610
#ifdef HAVE_WINDOWS_CONSOLE_IO
611
    Py_CLEAR(state->PyWindowsConsoleIO_Type);
612
#endif
613
0
    return 0;
614
0
}
615
616
static void
617
iomodule_free(void *mod)
618
0
{
619
0
    (void)iomodule_clear((PyObject *)mod);
620
0
}
621
622
623
/*
624
 * Module definition
625
 */
626
627
#define clinic_state() (get_io_state(module))
628
#include "clinic/_iomodule.c.h"
629
#undef clinic_state
630
631
static PyMethodDef module_methods[] = {
632
    _IO_OPEN_METHODDEF
633
    _IO_TEXT_ENCODING_METHODDEF
634
    _IO_OPEN_CODE_METHODDEF
635
    {NULL, NULL}
636
};
637
638
294
#define ADD_TYPE(module, type, spec, base)                               \
639
294
do {                                                                     \
640
294
    type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec,        \
641
294
                                                    (PyObject *)base);   \
642
294
    if (type == NULL) {                                                  \
643
0
        return -1;                                                       \
644
0
    }                                                                    \
645
294
    if (PyModule_AddType(module, type) < 0) {                            \
646
0
        return -1;                                                       \
647
0
    }                                                                    \
648
294
} while (0)
649
650
static int
651
iomodule_exec(PyObject *m)
652
21
{
653
21
    _PyIO_State *state = get_io_state(m);
654
655
    /* DEFAULT_BUFFER_SIZE */
656
21
    if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0)
657
0
        return -1;
658
659
    /* UnsupportedOperation inherits from ValueError and OSError */
660
21
    state->unsupported_operation = PyObject_CallFunction(
661
21
        (PyObject *)&PyType_Type, "s(OO){}",
662
21
        "UnsupportedOperation", PyExc_OSError, PyExc_ValueError);
663
21
    if (state->unsupported_operation == NULL)
664
0
        return -1;
665
21
    if (PyObject_SetAttrString(state->unsupported_operation,
666
21
                               "__module__", &_Py_ID(io)) < 0)
667
0
    {
668
0
        return -1;
669
0
    }
670
21
    if (PyModule_AddObjectRef(m, "UnsupportedOperation",
671
21
                              state->unsupported_operation) < 0)
672
0
    {
673
0
        return -1;
674
0
    }
675
676
    /* BlockingIOError, for compatibility */
677
21
    if (PyModule_AddObjectRef(m, "BlockingIOError",
678
21
                              (PyObject *) PyExc_BlockingIOError) < 0) {
679
0
        return -1;
680
0
    }
681
682
    // Base classes
683
21
    ADD_TYPE(m, state->PyIncrementalNewlineDecoder_Type, &_Py_nldecoder_spec, NULL);
684
21
    ADD_TYPE(m, state->PyBytesIOBuffer_Type, &_Py_bytesiobuf_spec, NULL);
685
21
    ADD_TYPE(m, state->PyIOBase_Type, &_Py_iobase_spec, NULL);
686
687
    // PyIOBase_Type subclasses
688
21
    ADD_TYPE(m, state->PyTextIOBase_Type, &_Py_textiobase_spec,
689
21
             state->PyIOBase_Type);
690
21
    ADD_TYPE(m, state->PyBufferedIOBase_Type, &_Py_bufferediobase_spec,
691
21
             state->PyIOBase_Type);
692
21
    ADD_TYPE(m, state->PyRawIOBase_Type, &_Py_rawiobase_spec,
693
21
             state->PyIOBase_Type);
694
695
    // PyBufferedIOBase_Type(PyIOBase_Type) subclasses
696
21
    ADD_TYPE(m, state->PyBytesIO_Type, &_Py_bytesio_spec, state->PyBufferedIOBase_Type);
697
21
    ADD_TYPE(m, state->PyBufferedWriter_Type, &_Py_bufferedwriter_spec,
698
21
             state->PyBufferedIOBase_Type);
699
21
    ADD_TYPE(m, state->PyBufferedReader_Type, &_Py_bufferedreader_spec,
700
21
             state->PyBufferedIOBase_Type);
701
21
    ADD_TYPE(m, state->PyBufferedRWPair_Type, &_Py_bufferedrwpair_spec,
702
21
             state->PyBufferedIOBase_Type);
703
21
    ADD_TYPE(m, state->PyBufferedRandom_Type, &_Py_bufferedrandom_spec,
704
21
             state->PyBufferedIOBase_Type);
705
706
    // PyRawIOBase_Type(PyIOBase_Type) subclasses
707
21
    ADD_TYPE(m, state->PyFileIO_Type, &_Py_fileio_spec, state->PyRawIOBase_Type);
708
709
#ifdef HAVE_WINDOWS_CONSOLE_IO
710
    ADD_TYPE(m, state->PyWindowsConsoleIO_Type, &_Py_winconsoleio_spec,
711
             state->PyRawIOBase_Type);
712
#endif
713
714
    // PyTextIOBase_Type(PyIOBase_Type) subclasses
715
21
    ADD_TYPE(m, state->PyStringIO_Type, &_Py_stringio_spec, state->PyTextIOBase_Type);
716
21
    ADD_TYPE(m, state->PyTextIOWrapper_Type, &_Py_textiowrapper_spec,
717
21
             state->PyTextIOBase_Type);
718
719
21
#undef ADD_TYPE
720
21
    return 0;
721
21
}
722
723
static struct PyModuleDef_Slot iomodule_slots[] = {
724
    _Py_ABI_SLOT,
725
    {Py_mod_exec, iomodule_exec},
726
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
727
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
728
    {0, NULL},
729
};
730
731
struct PyModuleDef _PyIO_Module = {
732
    .m_base = PyModuleDef_HEAD_INIT,
733
    .m_name = "io",
734
    .m_doc = module_doc,
735
    .m_size = sizeof(_PyIO_State),
736
    .m_methods = module_methods,
737
    .m_traverse = iomodule_traverse,
738
    .m_clear = iomodule_clear,
739
    .m_free = iomodule_free,
740
    .m_slots = iomodule_slots,
741
};
742
743
PyMODINIT_FUNC
744
PyInit__io(void)
745
21
{
746
21
    return PyModuleDef_Init(&_PyIO_Module);
747
21
}