Branch data Line data Source code
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 : :
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 : 1501 : _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 : 1501 : int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0;
204 : 1501 : int text = 0, binary = 0;
205 : :
206 : : char rawmode[6], *m;
207 : 1501 : int line_buffering, is_number, isatty = 0;
208 : :
209 : 1501 : PyObject *raw, *modeobj = NULL, *buffer, *wrapper, *result = NULL, *path_or_fd = NULL;
210 : :
211 : 1501 : is_number = PyNumber_Check(file);
212 : :
213 [ + + ]: 1501 : if (is_number) {
214 : 76 : path_or_fd = Py_NewRef(file);
215 : : } else {
216 : 1425 : path_or_fd = PyOS_FSPath(file);
217 [ - + ]: 1425 : if (path_or_fd == NULL) {
218 : 0 : return NULL;
219 : : }
220 : : }
221 : :
222 [ + + - + ]: 2926 : if (!is_number &&
223 [ - - ]: 1425 : !PyUnicode_Check(path_or_fd) &&
224 : 0 : !PyBytes_Check(path_or_fd)) {
225 : 0 : PyErr_Format(PyExc_TypeError, "invalid file: %R", file);
226 : 0 : goto error;
227 : : }
228 : :
229 : : /* Decode mode */
230 [ + + ]: 3825 : for (i = 0; i < strlen(mode); i++) {
231 : 2324 : char c = mode[i];
232 : :
233 [ - + + - : 2324 : switch (c) {
- - + - ]
234 : 0 : case 'x':
235 : 0 : creating = 1;
236 : 0 : break;
237 : 1427 : case 'r':
238 : 1427 : reading = 1;
239 : 1427 : break;
240 : 74 : case 'w':
241 : 74 : writing = 1;
242 : 74 : break;
243 : 0 : case 'a':
244 : 0 : appending = 1;
245 : 0 : break;
246 : 0 : case '+':
247 : 0 : updating = 1;
248 : 0 : break;
249 : 0 : case 't':
250 : 0 : text = 1;
251 : 0 : break;
252 : 823 : case 'b':
253 : 823 : binary = 1;
254 : 823 : break;
255 : 0 : default:
256 : 0 : goto invalid_mode;
257 : : }
258 : :
259 : : /* c must not be duplicated */
260 [ - + ]: 2324 : if (strchr(mode+i+1, c)) {
261 : 0 : invalid_mode:
262 : 0 : PyErr_Format(PyExc_ValueError, "invalid mode: '%s'", mode);
263 : 0 : goto error;
264 : : }
265 : :
266 : : }
267 : :
268 : 1501 : m = rawmode;
269 [ - + ]: 1501 : if (creating) *(m++) = 'x';
270 [ + + ]: 1501 : if (reading) *(m++) = 'r';
271 [ + + ]: 1501 : if (writing) *(m++) = 'w';
272 [ - + ]: 1501 : if (appending) *(m++) = 'a';
273 [ - + ]: 1501 : if (updating) *(m++) = '+';
274 : 1501 : *m = '\0';
275 : :
276 : : /* Parameters validation */
277 [ - + - - ]: 1501 : if (text && binary) {
278 : 0 : PyErr_SetString(PyExc_ValueError,
279 : : "can't have text and binary mode at once");
280 : 0 : goto error;
281 : : }
282 : :
283 [ - + ]: 1501 : if (creating + reading + writing + appending > 1) {
284 : 0 : PyErr_SetString(PyExc_ValueError,
285 : : "must have exactly one of create/read/write/append mode");
286 : 0 : goto error;
287 : : }
288 : :
289 [ + + - + ]: 1501 : if (binary && encoding != NULL) {
290 : 0 : PyErr_SetString(PyExc_ValueError,
291 : : "binary mode doesn't take an encoding argument");
292 : 0 : goto error;
293 : : }
294 : :
295 [ + + - + ]: 1501 : if (binary && errors != NULL) {
296 : 0 : PyErr_SetString(PyExc_ValueError,
297 : : "binary mode doesn't take an errors argument");
298 : 0 : goto error;
299 : : }
300 : :
301 [ + + - + ]: 1501 : if (binary && newline != NULL) {
302 : 0 : PyErr_SetString(PyExc_ValueError,
303 : : "binary mode doesn't take a newline argument");
304 : 0 : goto error;
305 : : }
306 : :
307 [ + + - + ]: 1501 : if (binary && buffering == 1) {
308 [ # # ]: 0 : 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 : 0 : goto error;
313 : : }
314 : : }
315 : :
316 : : /* Create the Raw file stream */
317 : 1501 : _PyIO_State *state = get_io_state(module);
318 : : {
319 : 1501 : 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 *)&PyWindowsConsoleIO_Type;
324 : : encoding = "utf-8";
325 : : }
326 : : #endif
327 [ + + ]: 1501 : raw = PyObject_CallFunction(RawIO_class, "OsOO",
328 : : path_or_fd, rawmode,
329 : : closefd ? Py_True : Py_False,
330 : : opener);
331 : : }
332 : :
333 [ + + ]: 1501 : if (raw == NULL)
334 : 160 : goto error;
335 : 1341 : result = raw;
336 : :
337 : 1341 : Py_SETREF(path_or_fd, NULL);
338 : :
339 : 1341 : modeobj = PyUnicode_FromString(mode);
340 [ - + ]: 1341 : if (modeobj == NULL)
341 : 0 : goto error;
342 : :
343 : : /* buffering */
344 [ + - ]: 1341 : if (buffering < 0) {
345 : 1341 : PyObject *res = PyObject_CallMethodNoArgs(raw, &_Py_ID(isatty));
346 [ - + ]: 1341 : if (res == NULL)
347 : 0 : goto error;
348 : 1341 : isatty = PyObject_IsTrue(res);
349 : 1341 : Py_DECREF(res);
350 [ - + ]: 1341 : if (isatty < 0)
351 : 0 : goto error;
352 : : }
353 : :
354 [ + - + + ]: 1341 : if (buffering == 1 || isatty) {
355 : 75 : buffering = -1;
356 : 75 : line_buffering = 1;
357 : : }
358 : : else
359 : 1266 : line_buffering = 0;
360 : :
361 [ + - ]: 1341 : if (buffering < 0) {
362 : : PyObject *blksize_obj;
363 : 1341 : blksize_obj = PyObject_GetAttr(raw, &_Py_ID(_blksize));
364 [ - + ]: 1341 : if (blksize_obj == NULL)
365 : 0 : goto error;
366 : 1341 : buffering = PyLong_AsLong(blksize_obj);
367 : 1341 : Py_DECREF(blksize_obj);
368 [ - + - - ]: 1341 : if (buffering == -1 && PyErr_Occurred())
369 : 0 : goto error;
370 : : }
371 [ - + ]: 1341 : if (buffering < 0) {
372 : 0 : PyErr_SetString(PyExc_ValueError,
373 : : "invalid buffering size");
374 : 0 : goto error;
375 : : }
376 : :
377 : : /* if not buffering, returns the raw file object */
378 [ - + ]: 1341 : if (buffering == 0) {
379 [ # # ]: 0 : if (!binary) {
380 : 0 : PyErr_SetString(PyExc_ValueError,
381 : : "can't have unbuffered text I/O");
382 : 0 : goto error;
383 : : }
384 : :
385 : 0 : Py_DECREF(modeobj);
386 : 0 : return result;
387 : : }
388 : :
389 : : /* wraps into a buffered file */
390 : : {
391 : : PyObject *Buffered_class;
392 : :
393 [ - + ]: 1341 : if (updating) {
394 : 0 : Buffered_class = (PyObject *)state->PyBufferedRandom_Type;
395 : : }
396 [ + - + + : 1341 : else if (creating || writing || appending) {
- + ]
397 : 74 : Buffered_class = (PyObject *)state->PyBufferedWriter_Type;
398 : : }
399 [ + - ]: 1267 : else if (reading) {
400 : 1267 : Buffered_class = (PyObject *)state->PyBufferedReader_Type;
401 : : }
402 : : else {
403 : 0 : PyErr_Format(PyExc_ValueError,
404 : : "unknown mode: '%s'", mode);
405 : 0 : goto error;
406 : : }
407 : :
408 : 1341 : buffer = PyObject_CallFunction(Buffered_class, "Oi", raw, buffering);
409 : : }
410 [ - + ]: 1341 : if (buffer == NULL)
411 : 0 : goto error;
412 : 1341 : result = buffer;
413 : 1341 : Py_DECREF(raw);
414 : :
415 : :
416 : : /* if binary, returns the buffered file */
417 [ + + ]: 1341 : if (binary) {
418 : 664 : Py_DECREF(modeobj);
419 : 664 : return result;
420 : : }
421 : :
422 : : /* wraps into a TextIOWrapper */
423 [ + + ]: 677 : wrapper = PyObject_CallFunction((PyObject *)state->PyTextIOWrapper_Type,
424 : : "OsssO",
425 : : buffer,
426 : : encoding, errors, newline,
427 : : line_buffering ? Py_True : Py_False);
428 [ - + ]: 677 : if (wrapper == NULL)
429 : 0 : goto error;
430 : 677 : result = wrapper;
431 : 677 : Py_DECREF(buffer);
432 : :
433 [ - + ]: 677 : if (PyObject_SetAttr(wrapper, &_Py_ID(mode), modeobj) < 0)
434 : 0 : goto error;
435 : 677 : Py_DECREF(modeobj);
436 : 677 : return result;
437 : :
438 : 160 : error:
439 [ - + ]: 160 : if (result != NULL) {
440 : 0 : PyObject *exc = PyErr_GetRaisedException();
441 : 0 : PyObject *close_result = PyObject_CallMethodNoArgs(result, &_Py_ID(close));
442 : 0 : _PyErr_ChainExceptions1(exc);
443 : 0 : Py_XDECREF(close_result);
444 : 0 : Py_DECREF(result);
445 : : }
446 : 160 : Py_XDECREF(path_or_fd);
447 : 160 : Py_XDECREF(modeobj);
448 : 160 : 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 : 0 : _io_text_encoding_impl(PyObject *module, PyObject *encoding, int stacklevel)
473 : : /*[clinic end generated code: output=91b2cfea6934cc0c input=4999aa8b3d90f3d4]*/
474 : : {
475 [ # # # # ]: 0 : if (encoding == NULL || encoding == Py_None) {
476 : 0 : PyInterpreterState *interp = _PyInterpreterState_GET();
477 [ # # ]: 0 : if (_PyInterpreterState_GetConfig(interp)->warn_default_encoding) {
478 [ # # ]: 0 : if (PyErr_WarnEx(PyExc_EncodingWarning,
479 : : "'encoding' argument not specified", stacklevel)) {
480 : 0 : return NULL;
481 : : }
482 : : }
483 : 0 : const PyPreConfig *preconfig = &_PyRuntime.preconfig;
484 [ # # ]: 0 : if (preconfig->utf8_mode) {
485 : : _Py_DECLARE_STR(utf_8, "utf-8");
486 : 0 : encoding = &_Py_STR(utf_8);
487 : : }
488 : : else {
489 : 0 : encoding = &_Py_ID(locale);
490 : : }
491 : : }
492 : 0 : 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 : 727 : _io_open_code_impl(PyObject *module, PyObject *path)
510 : : /*[clinic end generated code: output=2fe4ecbd6f3d6844 input=f5c18e23f4b2ed9f]*/
511 : : {
512 : 727 : return PyFile_OpenCodeObject(path);
513 : : }
514 : :
515 : : /*
516 : : * Private helpers for the io module.
517 : : */
518 : :
519 : : Py_off_t
520 : 1533 : PyNumber_AsOff_t(PyObject *item, PyObject *err)
521 : : {
522 : : Py_off_t result;
523 : : PyObject *runerr;
524 : 1533 : PyObject *value = _PyNumber_Index(item);
525 [ - + ]: 1533 : if (value == NULL)
526 : 0 : return -1;
527 : :
528 : : /* We're done if PyLong_AsSsize_t() returns without error. */
529 : 1533 : result = PyLong_AsOff_t(value);
530 [ - + - - ]: 1533 : if (result != -1 || !(runerr = PyErr_Occurred()))
531 : 1533 : goto finish;
532 : :
533 : : /* Error handling code -- only manage OverflowError differently */
534 [ # # ]: 0 : if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError))
535 : 0 : goto finish;
536 : :
537 : 0 : PyErr_Clear();
538 : : /* If no error-handling desired then the default clipping
539 : : is sufficient.
540 : : */
541 [ # # ]: 0 : 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 [ # # ]: 0 : if (_PyLong_Sign(value) < 0)
547 : 0 : result = PY_OFF_T_MIN;
548 : : else
549 : 0 : result = PY_OFF_T_MAX;
550 : : }
551 : : else {
552 : : /* Otherwise replace the error with caller's error object. */
553 : 0 : PyErr_Format(err,
554 : : "cannot fit '%.200s' into an offset-sized integer",
555 : 0 : Py_TYPE(item)->tp_name);
556 : : }
557 : :
558 : 1533 : finish:
559 : 1533 : Py_DECREF(value);
560 : 1533 : return result;
561 : : }
562 : :
563 : : _PyIO_State *
564 : 0 : _PyIO_get_module_state(void)
565 : : {
566 : 0 : PyObject *mod = PyState_FindModule(&_PyIO_Module);
567 : : _PyIO_State *state;
568 [ # # # # ]: 0 : if (mod == NULL || (state = get_io_state(mod)) == NULL) {
569 : 0 : PyErr_SetString(PyExc_RuntimeError,
570 : : "could not find io module state "
571 : : "(interpreter shutdown?)");
572 : 0 : return NULL;
573 : : }
574 : 0 : return state;
575 : : }
576 : :
577 : : static int
578 : 250 : iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
579 : 250 : _PyIO_State *state = get_io_state(mod);
580 [ - + ]: 250 : if (!state->initialized)
581 : 0 : return 0;
582 [ - + - - ]: 250 : Py_VISIT(state->locale_module);
583 [ + - - + ]: 250 : Py_VISIT(state->unsupported_operation);
584 : :
585 [ + - - + ]: 250 : Py_VISIT(state->PyBufferedRWPair_Type);
586 [ + - - + ]: 250 : Py_VISIT(state->PyBufferedRandom_Type);
587 [ + - - + ]: 250 : Py_VISIT(state->PyBufferedReader_Type);
588 [ + - - + ]: 250 : Py_VISIT(state->PyBufferedWriter_Type);
589 [ + - - + ]: 250 : Py_VISIT(state->PyBytesIO_Type);
590 [ + - - + ]: 250 : Py_VISIT(state->PyFileIO_Type);
591 [ + - - + ]: 250 : Py_VISIT(state->PyStringIO_Type);
592 [ + - - + ]: 250 : Py_VISIT(state->PyTextIOWrapper_Type);
593 : 250 : return 0;
594 : : }
595 : :
596 : :
597 : : static int
598 : 52 : iomodule_clear(PyObject *mod) {
599 : 52 : _PyIO_State *state = get_io_state(mod);
600 [ - + ]: 52 : if (!state->initialized)
601 : 0 : return 0;
602 [ - + ]: 52 : if (state->locale_module != NULL)
603 [ # # ]: 0 : Py_CLEAR(state->locale_module);
604 [ + + ]: 52 : Py_CLEAR(state->unsupported_operation);
605 : :
606 [ + + ]: 52 : Py_CLEAR(state->PyBufferedRWPair_Type);
607 [ + + ]: 52 : Py_CLEAR(state->PyBufferedRandom_Type);
608 [ + + ]: 52 : Py_CLEAR(state->PyBufferedReader_Type);
609 [ + + ]: 52 : Py_CLEAR(state->PyBufferedWriter_Type);
610 [ + + ]: 52 : Py_CLEAR(state->PyBytesIO_Type);
611 [ + + ]: 52 : Py_CLEAR(state->PyFileIO_Type);
612 [ + + ]: 52 : Py_CLEAR(state->PyStringIO_Type);
613 [ + + ]: 52 : Py_CLEAR(state->PyTextIOWrapper_Type);
614 : 52 : return 0;
615 : : }
616 : :
617 : : static void
618 : 26 : iomodule_free(PyObject *mod) {
619 : 26 : iomodule_clear(mod);
620 : 26 : }
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 : : struct PyModuleDef _PyIO_Module = {
639 : : PyModuleDef_HEAD_INIT,
640 : : "io",
641 : : module_doc,
642 : : sizeof(_PyIO_State),
643 : : module_methods,
644 : : NULL,
645 : : iomodule_traverse,
646 : : iomodule_clear,
647 : : (freefunc)iomodule_free,
648 : : };
649 : :
650 : :
651 : : static PyTypeObject* static_types[] = {
652 : : // Base classes
653 : : &PyIOBase_Type,
654 : : &PyIncrementalNewlineDecoder_Type,
655 : :
656 : : // PyIOBase_Type subclasses
657 : : &PyBufferedIOBase_Type,
658 : : &PyRawIOBase_Type,
659 : : &PyTextIOBase_Type,
660 : :
661 : : // PyRawIOBase_Type(PyIOBase_Type) subclasses
662 : : &_PyBytesIOBuffer_Type,
663 : : #ifdef HAVE_WINDOWS_CONSOLE_IO
664 : : &PyWindowsConsoleIO_Type,
665 : : #endif
666 : : };
667 : :
668 : :
669 : : void
670 : 25 : _PyIO_Fini(void)
671 : : {
672 [ + + ]: 175 : for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types) - 1; i >= 0; i--) {
673 : 150 : PyTypeObject *exc = static_types[i];
674 : 150 : _PyStaticType_Dealloc(exc);
675 : : }
676 : 25 : }
677 : :
678 : : #define ADD_TYPE(module, type, spec, base) \
679 : : do { \
680 : : type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \
681 : : (PyObject *)base); \
682 : : if (type == NULL) { \
683 : : goto fail; \
684 : : } \
685 : : if (PyModule_AddType(module, type) < 0) { \
686 : : goto fail; \
687 : : } \
688 : : } while (0)
689 : :
690 : : PyMODINIT_FUNC
691 : 26 : PyInit__io(void)
692 : : {
693 : 26 : PyObject *m = PyModule_Create(&_PyIO_Module);
694 : 26 : _PyIO_State *state = NULL;
695 [ - + ]: 26 : if (m == NULL)
696 : 0 : return NULL;
697 : 26 : state = get_io_state(m);
698 : 26 : state->initialized = 0;
699 : :
700 : : /* DEFAULT_BUFFER_SIZE */
701 [ - + ]: 26 : if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0)
702 : 0 : goto fail;
703 : :
704 : : /* UnsupportedOperation inherits from ValueError and OSError */
705 : 26 : state->unsupported_operation = PyObject_CallFunction(
706 : : (PyObject *)&PyType_Type, "s(OO){}",
707 : : "UnsupportedOperation", PyExc_OSError, PyExc_ValueError);
708 [ - + ]: 26 : if (state->unsupported_operation == NULL)
709 : 0 : goto fail;
710 [ - + ]: 26 : if (PyModule_AddObject(m, "UnsupportedOperation",
711 : : Py_NewRef(state->unsupported_operation)) < 0)
712 : 0 : goto fail;
713 : :
714 : : /* BlockingIOError, for compatibility */
715 [ - + ]: 26 : if (PyModule_AddObjectRef(m, "BlockingIOError",
716 : : (PyObject *) PyExc_BlockingIOError) < 0) {
717 : 0 : goto fail;
718 : : }
719 : :
720 : : // Set type base classes
721 : : #ifdef HAVE_WINDOWS_CONSOLE_IO
722 : : PyWindowsConsoleIO_Type.tp_base = &PyRawIOBase_Type;
723 : : #endif
724 : :
725 : : // Add types
726 [ + + ]: 182 : for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
727 : 156 : PyTypeObject *type = static_types[i];
728 [ - + ]: 156 : if (PyModule_AddType(m, type) < 0) {
729 : 0 : goto fail;
730 : : }
731 : : }
732 : :
733 : : // PyBufferedIOBase_Type(PyIOBase_Type) subclasses
734 [ - + - + ]: 26 : ADD_TYPE(m, state->PyBytesIO_Type, &bytesio_spec, &PyBufferedIOBase_Type);
735 [ - + - + ]: 26 : ADD_TYPE(m, state->PyBufferedWriter_Type, &bufferedwriter_spec,
736 : : &PyBufferedIOBase_Type);
737 [ - + - + ]: 26 : ADD_TYPE(m, state->PyBufferedReader_Type, &bufferedreader_spec,
738 : : &PyBufferedIOBase_Type);
739 [ - + - + ]: 26 : ADD_TYPE(m, state->PyBufferedRWPair_Type, &bufferedrwpair_spec,
740 : : &PyBufferedIOBase_Type);
741 [ - + - + ]: 26 : ADD_TYPE(m, state->PyBufferedRandom_Type, &bufferedrandom_spec,
742 : : &PyBufferedIOBase_Type);
743 : :
744 : : // PyRawIOBase_Type(PyIOBase_Type) subclasses
745 [ - + - + ]: 26 : ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, &PyRawIOBase_Type);
746 : :
747 : : // PyTextIOBase_Type(PyIOBase_Type) subclasses
748 [ - + - + ]: 26 : ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, &PyTextIOBase_Type);
749 [ - + - + ]: 26 : ADD_TYPE(m, state->PyTextIOWrapper_Type, &textiowrapper_spec,
750 : : &PyTextIOBase_Type);
751 : :
752 : 26 : state->initialized = 1;
753 : :
754 : 26 : return m;
755 : :
756 : 0 : fail:
757 : 0 : Py_XDECREF(state->unsupported_operation);
758 : 0 : Py_DECREF(m);
759 : 0 : return NULL;
760 : : }
|