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