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