LCOV - code coverage report
Current view: | top level - Modules/_io - _iomodule.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 160 | 256 | 62.5 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 8 | 10 | 80.0 %
|  |  | Branches: | 131 | 248 | 52.8 %

               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                 :            : }

Generated by: LCOV version 1.14