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_initconfig.h" // _PyStatus_OK()
13 #include "pycore_long.h" // _PyLong_Sign()
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. open() uses the file's blksize (as obtained by os.stat) if\n"
64 " possible.\n"
65 );
66
67
68 /*
69 * The main open() function
70 */
71 /*[clinic input]
72 module _io
73
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 chosen using a heuristic trying to determine the underlying device's
136 "block size" and falling back on `io.DEFAULT_BUFFER_SIZE`.
137 On many systems, the buffer will typically be 4096 or 8192 bytes 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 *
_io_open_impl(PyObject * module,PyObject * file,const char * mode,int buffering,const char * encoding,const char * errors,const char * newline,int closefd,PyObject * opener)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=cd034e7cdfbf4e78]*/
204 {
205 unsigned i;
206
207 int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0;
208 int text = 0, binary = 0;
209
210 char rawmode[6], *m;
211 int line_buffering, is_number, isatty = 0;
212
213 PyObject *raw, *modeobj = NULL, *buffer, *wrapper, *result = NULL, *path_or_fd = NULL;
214
215 is_number = PyNumber_Check(file);
216
217 if (is_number) {
218 path_or_fd = Py_NewRef(file);
219 } else {
220 path_or_fd = PyOS_FSPath(file);
221 if (path_or_fd == NULL) {
222 return NULL;
223 }
224 }
225
226 if (!is_number &&
227 !PyUnicode_Check(path_or_fd) &&
228 !PyBytes_Check(path_or_fd)) {
229 PyErr_Format(PyExc_TypeError, "invalid file: %R", file);
230 goto error;
231 }
232
233 /* Decode mode */
234 for (i = 0; i < strlen(mode); i++) {
235 char c = mode[i];
236
237 switch (c) {
238 case 'x':
239 creating = 1;
240 break;
241 case 'r':
242 reading = 1;
243 break;
244 case 'w':
245 writing = 1;
246 break;
247 case 'a':
248 appending = 1;
249 break;
250 case '+':
251 updating = 1;
252 break;
253 case 't':
254 text = 1;
255 break;
256 case 'b':
257 binary = 1;
258 break;
259 default:
260 goto invalid_mode;
261 }
262
263 /* c must not be duplicated */
264 if (strchr(mode+i+1, c)) {
265 invalid_mode:
266 PyErr_Format(PyExc_ValueError, "invalid mode: '%s'", mode);
267 goto error;
268 }
269
270 }
271
272 m = rawmode;
273 if (creating) *(m++) = 'x';
274 if (reading) *(m++) = 'r';
275 if (writing) *(m++) = 'w';
276 if (appending) *(m++) = 'a';
277 if (updating) *(m++) = '+';
278 *m = '\0';
279
280 /* Parameters validation */
281 if (text && binary) {
282 PyErr_SetString(PyExc_ValueError,
283 "can't have text and binary mode at once");
284 goto error;
285 }
286
287 if (creating + reading + writing + appending > 1) {
288 PyErr_SetString(PyExc_ValueError,
289 "must have exactly one of create/read/write/append mode");
290 goto error;
291 }
292
293 if (binary && encoding != NULL) {
294 PyErr_SetString(PyExc_ValueError,
295 "binary mode doesn't take an encoding argument");
296 goto error;
297 }
298
299 if (binary && errors != NULL) {
300 PyErr_SetString(PyExc_ValueError,
301 "binary mode doesn't take an errors argument");
302 goto error;
303 }
304
305 if (binary && newline != NULL) {
306 PyErr_SetString(PyExc_ValueError,
307 "binary mode doesn't take a newline argument");
308 goto error;
309 }
310
311 if (binary && buffering == 1) {
312 if (PyErr_WarnEx(PyExc_RuntimeWarning,
313 "line buffering (buffering=1) isn't supported in "
314 "binary mode, the default buffer size will be used",
315 1) < 0) {
316 goto error;
317 }
318 }
319
320 /* Create the Raw file stream */
321 _PyIO_State *state = get_io_state(module);
322 {
323 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 raw = PyObject_CallFunction(RawIO_class, "OsOO",
332 path_or_fd, rawmode,
333 closefd ? Py_True : Py_False,
334 opener);
335 }
336
337 if (raw == NULL)
338 goto error;
339 result = raw;
340
341 Py_SETREF(path_or_fd, NULL);
342
343 modeobj = PyUnicode_FromString(mode);
344 if (modeobj == NULL)
345 goto error;
346
347 /* buffering */
348 if (buffering < 0) {
349 PyObject *res = PyObject_CallMethodNoArgs(raw, &_Py_ID(isatty));
350 if (res == NULL)
351 goto error;
352 isatty = PyObject_IsTrue(res);
353 Py_DECREF(res);
354 if (isatty < 0)
355 goto error;
356 }
357
358 if (buffering == 1 || isatty) {
359 buffering = -1;
360 line_buffering = 1;
361 }
362 else
363 line_buffering = 0;
364
365 if (buffering < 0) {
366 PyObject *blksize_obj;
367 blksize_obj = PyObject_GetAttr(raw, &_Py_ID(_blksize));
368 if (blksize_obj == NULL)
369 goto error;
370 buffering = PyLong_AsLong(blksize_obj);
371 Py_DECREF(blksize_obj);
372 if (buffering == -1 && PyErr_Occurred())
373 goto error;
374 }
375 if (buffering < 0) {
376 PyErr_SetString(PyExc_ValueError,
377 "invalid buffering size");
378 goto error;
379 }
380
381 /* if not buffering, returns the raw file object */
382 if (buffering == 0) {
383 if (!binary) {
384 PyErr_SetString(PyExc_ValueError,
385 "can't have unbuffered text I/O");
386 goto error;
387 }
388
389 Py_DECREF(modeobj);
390 return result;
391 }
392
393 /* wraps into a buffered file */
394 {
395 PyObject *Buffered_class;
396
397 if (updating) {
398 Buffered_class = (PyObject *)state->PyBufferedRandom_Type;
399 }
400 else if (creating || writing || appending) {
401 Buffered_class = (PyObject *)state->PyBufferedWriter_Type;
402 }
403 else if (reading) {
404 Buffered_class = (PyObject *)state->PyBufferedReader_Type;
405 }
406 else {
407 PyErr_Format(PyExc_ValueError,
408 "unknown mode: '%s'", mode);
409 goto error;
410 }
411
412 buffer = PyObject_CallFunction(Buffered_class, "Oi", raw, buffering);
413 }
414 if (buffer == NULL)
415 goto error;
416 result = buffer;
417 Py_DECREF(raw);
418
419
420 /* if binary, returns the buffered file */
421 if (binary) {
422 Py_DECREF(modeobj);
423 return result;
424 }
425
426 /* wraps into a TextIOWrapper */
427 wrapper = PyObject_CallFunction((PyObject *)state->PyTextIOWrapper_Type,
428 "OsssO",
429 buffer,
430 encoding, errors, newline,
431 line_buffering ? Py_True : Py_False);
432 if (wrapper == NULL)
433 goto error;
434 result = wrapper;
435 Py_DECREF(buffer);
436
437 if (PyObject_SetAttr(wrapper, &_Py_ID(mode), modeobj) < 0)
438 goto error;
439 Py_DECREF(modeobj);
440 return result;
441
442 error:
443 if (result != NULL) {
444 PyObject *exc = PyErr_GetRaisedException();
445 PyObject *close_result = PyObject_CallMethodNoArgs(result, &_Py_ID(close));
446 _PyErr_ChainExceptions1(exc);
447 Py_XDECREF(close_result);
448 Py_DECREF(result);
449 }
450 Py_XDECREF(path_or_fd);
451 Py_XDECREF(modeobj);
452 return NULL;
453 }
454
455
456 /*[clinic input]
457 _io.text_encoding
458 encoding: object
459 stacklevel: int = 2
460 /
461
462 A helper function to choose the text encoding.
463
464 When encoding is not None, this function returns it.
465 Otherwise, this function returns the default text encoding
466 (i.e. "locale" or "utf-8" depends on UTF-8 mode).
467
468 This function emits an EncodingWarning if encoding is None and
469 sys.flags.warn_default_encoding is true.
470
471 This can be used in APIs with an encoding=None parameter.
472 However, please consider using encoding="utf-8" for new APIs.
473 [clinic start generated code]*/
474
475 static PyObject *
_io_text_encoding_impl(PyObject * module,PyObject * encoding,int stacklevel)476 _io_text_encoding_impl(PyObject *module, PyObject *encoding, int stacklevel)
477 /*[clinic end generated code: output=91b2cfea6934cc0c input=4999aa8b3d90f3d4]*/
478 {
479 if (encoding == NULL || encoding == Py_None) {
480 PyInterpreterState *interp = _PyInterpreterState_GET();
481 if (_PyInterpreterState_GetConfig(interp)->warn_default_encoding) {
482 if (PyErr_WarnEx(PyExc_EncodingWarning,
483 "'encoding' argument not specified", stacklevel)) {
484 return NULL;
485 }
486 }
487 const PyPreConfig *preconfig = &_PyRuntime.preconfig;
488 if (preconfig->utf8_mode) {
489 _Py_DECLARE_STR(utf_8, "utf-8");
490 encoding = &_Py_STR(utf_8);
491 }
492 else {
493 encoding = &_Py_ID(locale);
494 }
495 }
496 return Py_NewRef(encoding);
497 }
498
499
500 /*[clinic input]
501 _io.open_code
502
503 path : unicode
504
505 Opens the provided file with the intent to import the contents.
506
507 This may perform extra validation beyond open(), but is otherwise interchangeable
508 with calling open(path, 'rb').
509
510 [clinic start generated code]*/
511
512 static PyObject *
_io_open_code_impl(PyObject * module,PyObject * path)513 _io_open_code_impl(PyObject *module, PyObject *path)
514 /*[clinic end generated code: output=2fe4ecbd6f3d6844 input=f5c18e23f4b2ed9f]*/
515 {
516 return PyFile_OpenCodeObject(path);
517 }
518
519 /*
520 * Private helpers for the io module.
521 */
522
523 Py_off_t
PyNumber_AsOff_t(PyObject * item,PyObject * err)524 PyNumber_AsOff_t(PyObject *item, PyObject *err)
525 {
526 Py_off_t result;
527 PyObject *runerr;
528 PyObject *value = _PyNumber_Index(item);
529 if (value == NULL)
530 return -1;
531
532 /* We're done if PyLong_AsSsize_t() returns without error. */
533 result = PyLong_AsOff_t(value);
534 if (result != -1 || !(runerr = PyErr_Occurred()))
535 goto finish;
536
537 /* Error handling code -- only manage OverflowError differently */
538 if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError))
539 goto finish;
540
541 PyErr_Clear();
542 /* If no error-handling desired then the default clipping
543 is sufficient.
544 */
545 if (!err) {
546 assert(PyLong_Check(value));
547 /* Whether or not it is less than or equal to
548 zero is determined by the sign of ob_size
549 */
550 if (_PyLong_Sign(value) < 0)
551 result = PY_OFF_T_MIN;
552 else
553 result = PY_OFF_T_MAX;
554 }
555 else {
556 /* Otherwise replace the error with caller's error object. */
557 PyErr_Format(err,
558 "cannot fit '%.200s' into an offset-sized integer",
559 Py_TYPE(item)->tp_name);
560 }
561
562 finish:
563 Py_DECREF(value);
564 return result;
565 }
566
567 static int
iomodule_traverse(PyObject * mod,visitproc visit,void * arg)568 iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
569 _PyIO_State *state = get_io_state(mod);
570 Py_VISIT(state->unsupported_operation);
571
572 Py_VISIT(state->PyIOBase_Type);
573 Py_VISIT(state->PyIncrementalNewlineDecoder_Type);
574 Py_VISIT(state->PyRawIOBase_Type);
575 Py_VISIT(state->PyBufferedIOBase_Type);
576 Py_VISIT(state->PyBufferedRWPair_Type);
577 Py_VISIT(state->PyBufferedRandom_Type);
578 Py_VISIT(state->PyBufferedReader_Type);
579 Py_VISIT(state->PyBufferedWriter_Type);
580 Py_VISIT(state->PyBytesIOBuffer_Type);
581 Py_VISIT(state->PyBytesIO_Type);
582 Py_VISIT(state->PyFileIO_Type);
583 Py_VISIT(state->PyStringIO_Type);
584 Py_VISIT(state->PyTextIOBase_Type);
585 Py_VISIT(state->PyTextIOWrapper_Type);
586 #ifdef HAVE_WINDOWS_CONSOLE_IO
587 Py_VISIT(state->PyWindowsConsoleIO_Type);
588 #endif
589 return 0;
590 }
591
592
593 static int
iomodule_clear(PyObject * mod)594 iomodule_clear(PyObject *mod) {
595 _PyIO_State *state = get_io_state(mod);
596 Py_CLEAR(state->unsupported_operation);
597
598 Py_CLEAR(state->PyIOBase_Type);
599 Py_CLEAR(state->PyIncrementalNewlineDecoder_Type);
600 Py_CLEAR(state->PyRawIOBase_Type);
601 Py_CLEAR(state->PyBufferedIOBase_Type);
602 Py_CLEAR(state->PyBufferedRWPair_Type);
603 Py_CLEAR(state->PyBufferedRandom_Type);
604 Py_CLEAR(state->PyBufferedReader_Type);
605 Py_CLEAR(state->PyBufferedWriter_Type);
606 Py_CLEAR(state->PyBytesIOBuffer_Type);
607 Py_CLEAR(state->PyBytesIO_Type);
608 Py_CLEAR(state->PyFileIO_Type);
609 Py_CLEAR(state->PyStringIO_Type);
610 Py_CLEAR(state->PyTextIOBase_Type);
611 Py_CLEAR(state->PyTextIOWrapper_Type);
612 #ifdef HAVE_WINDOWS_CONSOLE_IO
613 Py_CLEAR(state->PyWindowsConsoleIO_Type);
614 #endif
615 return 0;
616 }
617
618 static void
iomodule_free(void * mod)619 iomodule_free(void *mod)
620 {
621 (void)iomodule_clear((PyObject *)mod);
622 }
623
624
625 /*
626 * Module definition
627 */
628
629 #define clinic_state() (get_io_state(module))
630 #include "clinic/_iomodule.c.h"
631 #undef clinic_state
632
633 static PyMethodDef module_methods[] = {
634 _IO_OPEN_METHODDEF
635 _IO_TEXT_ENCODING_METHODDEF
636 _IO_OPEN_CODE_METHODDEF
637 {NULL, NULL}
638 };
639
640 #define ADD_TYPE(module, type, spec, base) \
641 do { \
642 type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \
643 (PyObject *)base); \
644 if (type == NULL) { \
645 return -1; \
646 } \
647 if (PyModule_AddType(module, type) < 0) { \
648 return -1; \
649 } \
650 } while (0)
651
652 static int
iomodule_exec(PyObject * m)653 iomodule_exec(PyObject *m)
654 {
655 _PyIO_State *state = get_io_state(m);
656
657 /* DEFAULT_BUFFER_SIZE */
658 if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0)
659 return -1;
660
661 /* UnsupportedOperation inherits from ValueError and OSError */
662 state->unsupported_operation = PyObject_CallFunction(
663 (PyObject *)&PyType_Type, "s(OO){}",
664 "UnsupportedOperation", PyExc_OSError, PyExc_ValueError);
665 if (state->unsupported_operation == NULL)
666 return -1;
667 if (PyModule_AddObjectRef(m, "UnsupportedOperation",
668 state->unsupported_operation) < 0)
669 {
670 return -1;
671 }
672
673 /* BlockingIOError, for compatibility */
674 if (PyModule_AddObjectRef(m, "BlockingIOError",
675 (PyObject *) PyExc_BlockingIOError) < 0) {
676 return -1;
677 }
678
679 // Base classes
680 ADD_TYPE(m, state->PyIncrementalNewlineDecoder_Type, &nldecoder_spec, NULL);
681 ADD_TYPE(m, state->PyBytesIOBuffer_Type, &bytesiobuf_spec, NULL);
682 ADD_TYPE(m, state->PyIOBase_Type, &iobase_spec, NULL);
683
684 // PyIOBase_Type subclasses
685 ADD_TYPE(m, state->PyTextIOBase_Type, &textiobase_spec,
686 state->PyIOBase_Type);
687 ADD_TYPE(m, state->PyBufferedIOBase_Type, &bufferediobase_spec,
688 state->PyIOBase_Type);
689 ADD_TYPE(m, state->PyRawIOBase_Type, &rawiobase_spec,
690 state->PyIOBase_Type);
691
692 // PyBufferedIOBase_Type(PyIOBase_Type) subclasses
693 ADD_TYPE(m, state->PyBytesIO_Type, &bytesio_spec, state->PyBufferedIOBase_Type);
694 ADD_TYPE(m, state->PyBufferedWriter_Type, &bufferedwriter_spec,
695 state->PyBufferedIOBase_Type);
696 ADD_TYPE(m, state->PyBufferedReader_Type, &bufferedreader_spec,
697 state->PyBufferedIOBase_Type);
698 ADD_TYPE(m, state->PyBufferedRWPair_Type, &bufferedrwpair_spec,
699 state->PyBufferedIOBase_Type);
700 ADD_TYPE(m, state->PyBufferedRandom_Type, &bufferedrandom_spec,
701 state->PyBufferedIOBase_Type);
702
703 // PyRawIOBase_Type(PyIOBase_Type) subclasses
704 ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, state->PyRawIOBase_Type);
705
706 #ifdef HAVE_WINDOWS_CONSOLE_IO
707 ADD_TYPE(m, state->PyWindowsConsoleIO_Type, &winconsoleio_spec,
708 state->PyRawIOBase_Type);
709 #endif
710
711 // PyTextIOBase_Type(PyIOBase_Type) subclasses
712 ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, state->PyTextIOBase_Type);
713 ADD_TYPE(m, state->PyTextIOWrapper_Type, &textiowrapper_spec,
714 state->PyTextIOBase_Type);
715
716 #undef ADD_TYPE
717 return 0;
718 }
719
720 static struct PyModuleDef_Slot iomodule_slots[] = {
721 {Py_mod_exec, iomodule_exec},
722 {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
723 {Py_mod_gil, Py_MOD_GIL_NOT_USED},
724 {0, NULL},
725 };
726
727 struct PyModuleDef _PyIO_Module = {
728 .m_base = PyModuleDef_HEAD_INIT,
729 .m_name = "io",
730 .m_doc = module_doc,
731 .m_size = sizeof(_PyIO_State),
732 .m_methods = module_methods,
733 .m_traverse = iomodule_traverse,
734 .m_clear = iomodule_clear,
735 .m_free = iomodule_free,
736 .m_slots = iomodule_slots,
737 };
738
739 PyMODINIT_FUNC
PyInit__io(void)740 PyInit__io(void)
741 {
742 return PyModuleDef_Init(&_PyIO_Module);
743 }
744