LCOV - code coverage report
Current view: | top level - Modules/_io/clinic - _iomodule.c.h (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 70 | 116 | 60.3 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 2 | 3 | 66.7 %
|  |  | Branches: | 54 | 100 | 54.0 %

               Branch data     Line data    Source code
           1                 :            : /*[clinic input]
           2                 :            : preserve
           3                 :            : [clinic start generated code]*/
           4                 :            :
           5                 :            : #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
           6                 :            : #  include "pycore_gc.h"            // PyGC_Head
           7                 :            : #  include "pycore_runtime.h"       // _Py_ID()
           8                 :            : #endif
           9                 :            :
          10                 :            :
          11                 :            : PyDoc_STRVAR(_io_open__doc__,
          12                 :            : "open($module, /, file, mode=\'r\', buffering=-1, encoding=None,\n"
          13                 :            : "     errors=None, newline=None, closefd=True, opener=None)\n"
          14                 :            : "--\n"
          15                 :            : "\n"
          16                 :            : "Open file and return a stream.  Raise OSError upon failure.\n"
          17                 :            : "\n"
          18                 :            : "file is either a text or byte string giving the name (and the path\n"
          19                 :            : "if the file isn\'t in the current working directory) of the file to\n"
          20                 :            : "be opened or an integer file descriptor of the file to be\n"
          21                 :            : "wrapped. (If a file descriptor is given, it is closed when the\n"
          22                 :            : "returned I/O object is closed, unless closefd is set to False.)\n"
          23                 :            : "\n"
          24                 :            : "mode is an optional string that specifies the mode in which the file\n"
          25                 :            : "is opened. It defaults to \'r\' which means open for reading in text\n"
          26                 :            : "mode.  Other common values are \'w\' for writing (truncating the file if\n"
          27                 :            : "it already exists), \'x\' for creating and writing to a new file, and\n"
          28                 :            : "\'a\' for appending (which on some Unix systems, means that all writes\n"
          29                 :            : "append to the end of the file regardless of the current seek position).\n"
          30                 :            : "In text mode, if encoding is not specified the encoding used is platform\n"
          31                 :            : "dependent: locale.getencoding() is called to get the current locale encoding.\n"
          32                 :            : "(For reading and writing raw bytes use binary mode and leave encoding\n"
          33                 :            : "unspecified.) The available modes are:\n"
          34                 :            : "\n"
          35                 :            : "========= ===============================================================\n"
          36                 :            : "Character Meaning\n"
          37                 :            : "--------- ---------------------------------------------------------------\n"
          38                 :            : "\'r\'       open for reading (default)\n"
          39                 :            : "\'w\'       open for writing, truncating the file first\n"
          40                 :            : "\'x\'       create a new file and open it for writing\n"
          41                 :            : "\'a\'       open for writing, appending to the end of the file if it exists\n"
          42                 :            : "\'b\'       binary mode\n"
          43                 :            : "\'t\'       text mode (default)\n"
          44                 :            : "\'+\'       open a disk file for updating (reading and writing)\n"
          45                 :            : "========= ===============================================================\n"
          46                 :            : "\n"
          47                 :            : "The default mode is \'rt\' (open for reading text). For binary random\n"
          48                 :            : "access, the mode \'w+b\' opens and truncates the file to 0 bytes, while\n"
          49                 :            : "\'r+b\' opens the file without truncation. The \'x\' mode implies \'w\' and\n"
          50                 :            : "raises an `FileExistsError` if the file already exists.\n"
          51                 :            : "\n"
          52                 :            : "Python distinguishes between files opened in binary and text modes,\n"
          53                 :            : "even when the underlying operating system doesn\'t. Files opened in\n"
          54                 :            : "binary mode (appending \'b\' to the mode argument) return contents as\n"
          55                 :            : "bytes objects without any decoding. In text mode (the default, or when\n"
          56                 :            : "\'t\' is appended to the mode argument), the contents of the file are\n"
          57                 :            : "returned as strings, the bytes having been first decoded using a\n"
          58                 :            : "platform-dependent encoding or using the specified encoding if given.\n"
          59                 :            : "\n"
          60                 :            : "buffering is an optional integer used to set the buffering policy.\n"
          61                 :            : "Pass 0 to switch buffering off (only allowed in binary mode), 1 to select\n"
          62                 :            : "line buffering (only usable in text mode), and an integer > 1 to indicate\n"
          63                 :            : "the size of a fixed-size chunk buffer.  When no buffering argument is\n"
          64                 :            : "given, the default buffering policy works as follows:\n"
          65                 :            : "\n"
          66                 :            : "* Binary files are buffered in fixed-size chunks; the size of the buffer\n"
          67                 :            : "  is chosen using a heuristic trying to determine the underlying device\'s\n"
          68                 :            : "  \"block size\" and falling back on `io.DEFAULT_BUFFER_SIZE`.\n"
          69                 :            : "  On many systems, the buffer will typically be 4096 or 8192 bytes long.\n"
          70                 :            : "\n"
          71                 :            : "* \"Interactive\" text files (files for which isatty() returns True)\n"
          72                 :            : "  use line buffering.  Other text files use the policy described above\n"
          73                 :            : "  for binary files.\n"
          74                 :            : "\n"
          75                 :            : "encoding is the name of the encoding used to decode or encode the\n"
          76                 :            : "file. This should only be used in text mode. The default encoding is\n"
          77                 :            : "platform dependent, but any encoding supported by Python can be\n"
          78                 :            : "passed.  See the codecs module for the list of supported encodings.\n"
          79                 :            : "\n"
          80                 :            : "errors is an optional string that specifies how encoding errors are to\n"
          81                 :            : "be handled---this argument should not be used in binary mode. Pass\n"
          82                 :            : "\'strict\' to raise a ValueError exception if there is an encoding error\n"
          83                 :            : "(the default of None has the same effect), or pass \'ignore\' to ignore\n"
          84                 :            : "errors. (Note that ignoring encoding errors can lead to data loss.)\n"
          85                 :            : "See the documentation for codecs.register or run \'help(codecs.Codec)\'\n"
          86                 :            : "for a list of the permitted encoding error strings.\n"
          87                 :            : "\n"
          88                 :            : "newline controls how universal newlines works (it only applies to text\n"
          89                 :            : "mode). It can be None, \'\', \'\\n\', \'\\r\', and \'\\r\\n\'.  It works as\n"
          90                 :            : "follows:\n"
          91                 :            : "\n"
          92                 :            : "* On input, if newline is None, universal newlines mode is\n"
          93                 :            : "  enabled. Lines in the input can end in \'\\n\', \'\\r\', or \'\\r\\n\', and\n"
          94                 :            : "  these are translated into \'\\n\' before being returned to the\n"
          95                 :            : "  caller. If it is \'\', universal newline mode is enabled, but line\n"
          96                 :            : "  endings are returned to the caller untranslated. If it has any of\n"
          97                 :            : "  the other legal values, input lines are only terminated by the given\n"
          98                 :            : "  string, and the line ending is returned to the caller untranslated.\n"
          99                 :            : "\n"
         100                 :            : "* On output, if newline is None, any \'\\n\' characters written are\n"
         101                 :            : "  translated to the system default line separator, os.linesep. If\n"
         102                 :            : "  newline is \'\' or \'\\n\', no translation takes place. If newline is any\n"
         103                 :            : "  of the other legal values, any \'\\n\' characters written are translated\n"
         104                 :            : "  to the given string.\n"
         105                 :            : "\n"
         106                 :            : "If closefd is False, the underlying file descriptor will be kept open\n"
         107                 :            : "when the file is closed. This does not work when a file name is given\n"
         108                 :            : "and must be True in that case.\n"
         109                 :            : "\n"
         110                 :            : "A custom opener can be used by passing a callable as *opener*. The\n"
         111                 :            : "underlying file descriptor for the file object is then obtained by\n"
         112                 :            : "calling *opener* with (*file*, *flags*). *opener* must return an open\n"
         113                 :            : "file descriptor (passing os.open as *opener* results in functionality\n"
         114                 :            : "similar to passing None).\n"
         115                 :            : "\n"
         116                 :            : "open() returns a file object whose type depends on the mode, and\n"
         117                 :            : "through which the standard file operations such as reading and writing\n"
         118                 :            : "are performed. When open() is used to open a file in a text mode (\'w\',\n"
         119                 :            : "\'r\', \'wt\', \'rt\', etc.), it returns a TextIOWrapper. When used to open\n"
         120                 :            : "a file in a binary mode, the returned class varies: in read binary\n"
         121                 :            : "mode, it returns a BufferedReader; in write binary and append binary\n"
         122                 :            : "modes, it returns a BufferedWriter, and in read/write mode, it returns\n"
         123                 :            : "a BufferedRandom.\n"
         124                 :            : "\n"
         125                 :            : "It is also possible to use a string or bytearray as a file for both\n"
         126                 :            : "reading and writing. For strings StringIO can be used like a file\n"
         127                 :            : "opened in a text mode, and for bytes a BytesIO can be used like a file\n"
         128                 :            : "opened in a binary mode.");
         129                 :            :
         130                 :            : #define _IO_OPEN_METHODDEF    \
         131                 :            :     {"open", _PyCFunction_CAST(_io_open), METH_FASTCALL|METH_KEYWORDS, _io_open__doc__},
         132                 :            :
         133                 :            : static PyObject *
         134                 :            : _io_open_impl(PyObject *module, PyObject *file, const char *mode,
         135                 :            :               int buffering, const char *encoding, const char *errors,
         136                 :            :               const char *newline, int closefd, PyObject *opener);
         137                 :            :
         138                 :            : static PyObject *
         139                 :       1501 : _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
         140                 :            : {
         141                 :       1501 :     PyObject *return_value = NULL;
         142                 :            :     #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
         143                 :            :
         144                 :            :     #define NUM_KEYWORDS 8
         145                 :            :     static struct {
         146                 :            :         PyGC_Head _this_is_not_used;
         147                 :            :         PyObject_VAR_HEAD
         148                 :            :         PyObject *ob_item[NUM_KEYWORDS];
         149                 :            :     } _kwtuple = {
         150                 :            :         .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
         151                 :            :         .ob_item = { &_Py_ID(file), &_Py_ID(mode), &_Py_ID(buffering), &_Py_ID(encoding), &_Py_ID(errors), &_Py_ID(newline), &_Py_ID(closefd), &_Py_ID(opener), },
         152                 :            :     };
         153                 :            :     #undef NUM_KEYWORDS
         154                 :            :     #define KWTUPLE (&_kwtuple.ob_base.ob_base)
         155                 :            :
         156                 :            :     #else  // !Py_BUILD_CORE
         157                 :            :     #  define KWTUPLE NULL
         158                 :            :     #endif  // !Py_BUILD_CORE
         159                 :            :
         160                 :            :     static const char * const _keywords[] = {"file", "mode", "buffering", "encoding", "errors", "newline", "closefd", "opener", NULL};
         161                 :            :     static _PyArg_Parser _parser = {
         162                 :            :         .keywords = _keywords,
         163                 :            :         .fname = "open",
         164                 :            :         .kwtuple = KWTUPLE,
         165                 :            :     };
         166                 :            :     #undef KWTUPLE
         167                 :            :     PyObject *argsbuf[8];
         168         [ +  + ]:       1501 :     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
         169                 :            :     PyObject *file;
         170                 :       1501 :     const char *mode = "r";
         171                 :       1501 :     int buffering = -1;
         172                 :       1501 :     const char *encoding = NULL;
         173                 :       1501 :     const char *errors = NULL;
         174                 :       1501 :     const char *newline = NULL;
         175                 :       1501 :     int closefd = 1;
         176                 :       1501 :     PyObject *opener = Py_None;
         177                 :            :
         178   [ +  +  +  -  :       1501 :     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 8, 0, argsbuf);
                 +  -  -  + ]
         179         [ -  + ]:       1501 :     if (!args) {
         180                 :          0 :         goto exit;
         181                 :            :     }
         182                 :       1501 :     file = args[0];
         183         [ -  + ]:       1501 :     if (!noptargs) {
         184                 :          0 :         goto skip_optional_pos;
         185                 :            :     }
         186         [ +  + ]:       1501 :     if (args[1]) {
         187         [ -  + ]:        870 :         if (!PyUnicode_Check(args[1])) {
         188                 :          0 :             _PyArg_BadArgument("open", "argument 'mode'", "str", args[1]);
         189                 :          0 :             goto exit;
         190                 :            :         }
         191                 :            :         Py_ssize_t mode_length;
         192                 :        870 :         mode = PyUnicode_AsUTF8AndSize(args[1], &mode_length);
         193         [ -  + ]:        870 :         if (mode == NULL) {
         194                 :          0 :             goto exit;
         195                 :            :         }
         196         [ -  + ]:        870 :         if (strlen(mode) != (size_t)mode_length) {
         197                 :          0 :             PyErr_SetString(PyExc_ValueError, "embedded null character");
         198                 :          0 :             goto exit;
         199                 :            :         }
         200         [ +  + ]:        870 :         if (!--noptargs) {
         201                 :        768 :             goto skip_optional_pos;
         202                 :            :         }
         203                 :            :     }
         204         [ +  + ]:        733 :     if (args[2]) {
         205                 :         75 :         buffering = _PyLong_AsInt(args[2]);
         206   [ +  -  -  + ]:         75 :         if (buffering == -1 && PyErr_Occurred()) {
         207                 :          0 :             goto exit;
         208                 :            :         }
         209         [ -  + ]:         75 :         if (!--noptargs) {
         210                 :          0 :             goto skip_optional_pos;
         211                 :            :         }
         212                 :            :     }
         213         [ +  - ]:        733 :     if (args[3]) {
         214         [ +  + ]:        733 :         if (args[3] == Py_None) {
         215                 :         75 :             encoding = NULL;
         216                 :            :         }
         217         [ +  - ]:        658 :         else if (PyUnicode_Check(args[3])) {
         218                 :            :             Py_ssize_t encoding_length;
         219                 :        658 :             encoding = PyUnicode_AsUTF8AndSize(args[3], &encoding_length);
         220         [ -  + ]:        658 :             if (encoding == NULL) {
         221                 :          0 :                 goto exit;
         222                 :            :             }
         223         [ -  + ]:        658 :             if (strlen(encoding) != (size_t)encoding_length) {
         224                 :          0 :                 PyErr_SetString(PyExc_ValueError, "embedded null character");
         225                 :          0 :                 goto exit;
         226                 :            :             }
         227                 :            :         }
         228                 :            :         else {
         229                 :          0 :             _PyArg_BadArgument("open", "argument 'encoding'", "str or None", args[3]);
         230                 :          0 :             goto exit;
         231                 :            :         }
         232         [ +  + ]:        733 :         if (!--noptargs) {
         233                 :        656 :             goto skip_optional_pos;
         234                 :            :         }
         235                 :            :     }
         236         [ +  - ]:         77 :     if (args[4]) {
         237         [ +  + ]:         77 :         if (args[4] == Py_None) {
         238                 :         75 :             errors = NULL;
         239                 :            :         }
         240         [ +  - ]:          2 :         else if (PyUnicode_Check(args[4])) {
         241                 :            :             Py_ssize_t errors_length;
         242                 :          2 :             errors = PyUnicode_AsUTF8AndSize(args[4], &errors_length);
         243         [ -  + ]:          2 :             if (errors == NULL) {
         244                 :          0 :                 goto exit;
         245                 :            :             }
         246         [ -  + ]:          2 :             if (strlen(errors) != (size_t)errors_length) {
         247                 :          0 :                 PyErr_SetString(PyExc_ValueError, "embedded null character");
         248                 :          0 :                 goto exit;
         249                 :            :             }
         250                 :            :         }
         251                 :            :         else {
         252                 :          0 :             _PyArg_BadArgument("open", "argument 'errors'", "str or None", args[4]);
         253                 :          0 :             goto exit;
         254                 :            :         }
         255         [ +  + ]:         77 :         if (!--noptargs) {
         256                 :          1 :             goto skip_optional_pos;
         257                 :            :         }
         258                 :            :     }
         259         [ +  - ]:         76 :     if (args[5]) {
         260         [ +  + ]:         76 :         if (args[5] == Py_None) {
         261                 :         75 :             newline = NULL;
         262                 :            :         }
         263         [ +  - ]:          1 :         else if (PyUnicode_Check(args[5])) {
         264                 :            :             Py_ssize_t newline_length;
         265                 :          1 :             newline = PyUnicode_AsUTF8AndSize(args[5], &newline_length);
         266         [ -  + ]:          1 :             if (newline == NULL) {
         267                 :          0 :                 goto exit;
         268                 :            :             }
         269         [ -  + ]:          1 :             if (strlen(newline) != (size_t)newline_length) {
         270                 :          0 :                 PyErr_SetString(PyExc_ValueError, "embedded null character");
         271                 :          0 :                 goto exit;
         272                 :            :             }
         273                 :            :         }
         274                 :            :         else {
         275                 :          0 :             _PyArg_BadArgument("open", "argument 'newline'", "str or None", args[5]);
         276                 :          0 :             goto exit;
         277                 :            :         }
         278         [ -  + ]:         76 :         if (!--noptargs) {
         279                 :          0 :             goto skip_optional_pos;
         280                 :            :         }
         281                 :            :     }
         282         [ +  - ]:         76 :     if (args[6]) {
         283                 :         76 :         closefd = PyObject_IsTrue(args[6]);
         284         [ -  + ]:         76 :         if (closefd < 0) {
         285                 :          0 :             goto exit;
         286                 :            :         }
         287         [ +  - ]:         76 :         if (!--noptargs) {
         288                 :         76 :             goto skip_optional_pos;
         289                 :            :         }
         290                 :            :     }
         291                 :          0 :     opener = args[7];
         292                 :       1501 : skip_optional_pos:
         293                 :       1501 :     return_value = _io_open_impl(module, file, mode, buffering, encoding, errors, newline, closefd, opener);
         294                 :            :
         295                 :       1501 : exit:
         296                 :       1501 :     return return_value;
         297                 :            : }
         298                 :            :
         299                 :            : PyDoc_STRVAR(_io_text_encoding__doc__,
         300                 :            : "text_encoding($module, encoding, stacklevel=2, /)\n"
         301                 :            : "--\n"
         302                 :            : "\n"
         303                 :            : "A helper function to choose the text encoding.\n"
         304                 :            : "\n"
         305                 :            : "When encoding is not None, this function returns it.\n"
         306                 :            : "Otherwise, this function returns the default text encoding\n"
         307                 :            : "(i.e. \"locale\" or \"utf-8\" depends on UTF-8 mode).\n"
         308                 :            : "\n"
         309                 :            : "This function emits an EncodingWarning if encoding is None and\n"
         310                 :            : "sys.flags.warn_default_encoding is true.\n"
         311                 :            : "\n"
         312                 :            : "This can be used in APIs with an encoding=None parameter.\n"
         313                 :            : "However, please consider using encoding=\"utf-8\" for new APIs.");
         314                 :            :
         315                 :            : #define _IO_TEXT_ENCODING_METHODDEF    \
         316                 :            :     {"text_encoding", _PyCFunction_CAST(_io_text_encoding), METH_FASTCALL, _io_text_encoding__doc__},
         317                 :            :
         318                 :            : static PyObject *
         319                 :            : _io_text_encoding_impl(PyObject *module, PyObject *encoding, int stacklevel);
         320                 :            :
         321                 :            : static PyObject *
         322                 :          0 : _io_text_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
         323                 :            : {
         324                 :          0 :     PyObject *return_value = NULL;
         325                 :            :     PyObject *encoding;
         326                 :          0 :     int stacklevel = 2;
         327                 :            :
         328   [ #  #  #  #  :          0 :     if (!_PyArg_CheckPositional("text_encoding", nargs, 1, 2)) {
                       #  # ]
         329                 :          0 :         goto exit;
         330                 :            :     }
         331                 :          0 :     encoding = args[0];
         332         [ #  # ]:          0 :     if (nargs < 2) {
         333                 :          0 :         goto skip_optional;
         334                 :            :     }
         335                 :          0 :     stacklevel = _PyLong_AsInt(args[1]);
         336   [ #  #  #  # ]:          0 :     if (stacklevel == -1 && PyErr_Occurred()) {
         337                 :          0 :         goto exit;
         338                 :            :     }
         339                 :          0 : skip_optional:
         340                 :          0 :     return_value = _io_text_encoding_impl(module, encoding, stacklevel);
         341                 :            :
         342                 :          0 : exit:
         343                 :          0 :     return return_value;
         344                 :            : }
         345                 :            :
         346                 :            : PyDoc_STRVAR(_io_open_code__doc__,
         347                 :            : "open_code($module, /, path)\n"
         348                 :            : "--\n"
         349                 :            : "\n"
         350                 :            : "Opens the provided file with the intent to import the contents.\n"
         351                 :            : "\n"
         352                 :            : "This may perform extra validation beyond open(), but is otherwise interchangeable\n"
         353                 :            : "with calling open(path, \'rb\').");
         354                 :            :
         355                 :            : #define _IO_OPEN_CODE_METHODDEF    \
         356                 :            :     {"open_code", _PyCFunction_CAST(_io_open_code), METH_FASTCALL|METH_KEYWORDS, _io_open_code__doc__},
         357                 :            :
         358                 :            : static PyObject *
         359                 :            : _io_open_code_impl(PyObject *module, PyObject *path);
         360                 :            :
         361                 :            : static PyObject *
         362                 :        727 : _io_open_code(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
         363                 :            : {
         364                 :        727 :     PyObject *return_value = NULL;
         365                 :            :     #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
         366                 :            :
         367                 :            :     #define NUM_KEYWORDS 1
         368                 :            :     static struct {
         369                 :            :         PyGC_Head _this_is_not_used;
         370                 :            :         PyObject_VAR_HEAD
         371                 :            :         PyObject *ob_item[NUM_KEYWORDS];
         372                 :            :     } _kwtuple = {
         373                 :            :         .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
         374                 :            :         .ob_item = { &_Py_ID(path), },
         375                 :            :     };
         376                 :            :     #undef NUM_KEYWORDS
         377                 :            :     #define KWTUPLE (&_kwtuple.ob_base.ob_base)
         378                 :            :
         379                 :            :     #else  // !Py_BUILD_CORE
         380                 :            :     #  define KWTUPLE NULL
         381                 :            :     #endif  // !Py_BUILD_CORE
         382                 :            :
         383                 :            :     static const char * const _keywords[] = {"path", NULL};
         384                 :            :     static _PyArg_Parser _parser = {
         385                 :            :         .keywords = _keywords,
         386                 :            :         .fname = "open_code",
         387                 :            :         .kwtuple = KWTUPLE,
         388                 :            :     };
         389                 :            :     #undef KWTUPLE
         390                 :            :     PyObject *argsbuf[1];
         391                 :            :     PyObject *path;
         392                 :            :
         393   [ +  -  +  -  :        727 :     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
                 +  -  -  + ]
         394         [ -  + ]:        727 :     if (!args) {
         395                 :          0 :         goto exit;
         396                 :            :     }
         397         [ -  + ]:        727 :     if (!PyUnicode_Check(args[0])) {
         398                 :          0 :         _PyArg_BadArgument("open_code", "argument 'path'", "str", args[0]);
         399                 :          0 :         goto exit;
         400                 :            :     }
         401         [ -  + ]:        727 :     if (PyUnicode_READY(args[0]) == -1) {
         402                 :          0 :         goto exit;
         403                 :            :     }
         404                 :        727 :     path = args[0];
         405                 :        727 :     return_value = _io_open_code_impl(module, path);
         406                 :            :
         407                 :        727 : exit:
         408                 :        727 :     return return_value;
         409                 :            : }
         410                 :            : /*[clinic end generated code: output=f387eba3f4c0254a input=a9049054013a1b77]*/

Generated by: LCOV version 1.14