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