LCOV - code coverage report
Current view: top level - Modules/_io - _iomodule.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 60 280 21.4 %
Date: 2017-04-19 Functions: 1 5 20.0 %

          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 "structmember.h"
      13             : #include "_iomodule.h"
      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             : 
      24             : /* Various interned strings */
      25             : 
      26             : PyObject *_PyIO_str_close;
      27             : PyObject *_PyIO_str_closed;
      28             : PyObject *_PyIO_str_decode;
      29             : PyObject *_PyIO_str_encode;
      30             : PyObject *_PyIO_str_fileno;
      31             : PyObject *_PyIO_str_flush;
      32             : PyObject *_PyIO_str_getstate;
      33             : PyObject *_PyIO_str_isatty;
      34             : PyObject *_PyIO_str_newlines;
      35             : PyObject *_PyIO_str_nl;
      36             : PyObject *_PyIO_str_read;
      37             : PyObject *_PyIO_str_read1;
      38             : PyObject *_PyIO_str_readable;
      39             : PyObject *_PyIO_str_readinto;
      40             : PyObject *_PyIO_str_readline;
      41             : PyObject *_PyIO_str_reset;
      42             : PyObject *_PyIO_str_seek;
      43             : PyObject *_PyIO_str_seekable;
      44             : PyObject *_PyIO_str_setstate;
      45             : PyObject *_PyIO_str_tell;
      46             : PyObject *_PyIO_str_truncate;
      47             : PyObject *_PyIO_str_writable;
      48             : PyObject *_PyIO_str_write;
      49             : 
      50             : PyObject *_PyIO_empty_str;
      51             : PyObject *_PyIO_empty_bytes;
      52             : PyObject *_PyIO_zero;
      53             : 
      54             : 
      55             : PyDoc_STRVAR(module_doc,
      56             : "The io module provides the Python interfaces to stream handling. The\n"
      57             : "builtin open function is defined in this module.\n"
      58             : "\n"
      59             : "At the top of the I/O hierarchy is the abstract base class IOBase. It\n"
      60             : "defines the basic interface to a stream. Note, however, that there is no\n"
      61             : "separation between reading and writing to streams; implementations are\n"
      62             : "allowed to raise an IOError if they do not support a given operation.\n"
      63             : "\n"
      64             : "Extending IOBase is RawIOBase which deals simply with the reading and\n"
      65             : "writing of raw bytes to a stream. FileIO subclasses RawIOBase to provide\n"
      66             : "an interface to OS files.\n"
      67             : "\n"
      68             : "BufferedIOBase deals with buffering on a raw byte stream (RawIOBase). Its\n"
      69             : "subclasses, BufferedWriter, BufferedReader, and BufferedRWPair buffer\n"
      70             : "streams that are readable, writable, and both respectively.\n"
      71             : "BufferedRandom provides a buffered interface to random access\n"
      72             : "streams. BytesIO is a simple stream of in-memory bytes.\n"
      73             : "\n"
      74             : "Another IOBase subclass, TextIOBase, deals with the encoding and decoding\n"
      75             : "of streams into text. TextIOWrapper, which extends it, is a buffered text\n"
      76             : "interface to a buffered raw stream (`BufferedIOBase`). Finally, StringIO\n"
      77             : "is an in-memory stream for text.\n"
      78             : "\n"
      79             : "Argument names are not part of the specification, and only the arguments\n"
      80             : "of open() are intended to be used as keyword arguments.\n"
      81             : "\n"
      82             : "data:\n"
      83             : "\n"
      84             : "DEFAULT_BUFFER_SIZE\n"
      85             : "\n"
      86             : "   An int containing the default buffer size used by the module's buffered\n"
      87             : "   I/O classes. open() uses the file's blksize (as obtained by os.stat) if\n"
      88             : "   possible.\n"
      89             :     );
      90             : 
      91             : 
      92             : /*
      93             :  * BlockingIOError extends IOError
      94             :  */
      95             : 
      96             : static int
      97           0 : blockingioerror_init(PyBlockingIOErrorObject *self, PyObject *args,
      98             :                      PyObject *kwds)
      99             : {
     100           0 :     PyObject *myerrno = NULL, *strerror = NULL;
     101           0 :     PyObject *baseargs = NULL;
     102           0 :     Py_ssize_t written = 0;
     103             : 
     104             :     assert(PyTuple_Check(args));
     105             : 
     106           0 :     self->written = 0;
     107           0 :     if (!PyArg_ParseTuple(args, "OO|n:BlockingIOError",
     108             :                           &myerrno, &strerror, &written))
     109           0 :         return -1;
     110             : 
     111           0 :     baseargs = PyTuple_Pack(2, myerrno, strerror);
     112           0 :     if (baseargs == NULL)
     113           0 :         return -1;
     114             :     /* This will take care of initializing of myerrno and strerror members */
     115           0 :     if (((PyTypeObject *)PyExc_IOError)->tp_init(
     116             :                 (PyObject *)self, baseargs, kwds) == -1) {
     117           0 :         Py_DECREF(baseargs);
     118           0 :         return -1;
     119             :     }
     120           0 :     Py_DECREF(baseargs);
     121             : 
     122           0 :     self->written = written;
     123           0 :     return 0;
     124             : }
     125             : 
     126             : static PyMemberDef blockingioerror_members[] = {
     127             :     {"characters_written", T_PYSSIZET, offsetof(PyBlockingIOErrorObject, written), 0},
     128             :     {NULL}  /* Sentinel */
     129             : };
     130             : 
     131             : static PyTypeObject _PyExc_BlockingIOError = {
     132             :     PyVarObject_HEAD_INIT(NULL, 0)
     133             :     "BlockingIOError", /*tp_name*/
     134             :     sizeof(PyBlockingIOErrorObject), /*tp_basicsize*/
     135             :     0,                          /*tp_itemsize*/
     136             :     0,                          /*tp_dealloc*/
     137             :     0,                          /*tp_print*/
     138             :     0,                          /*tp_getattr*/
     139             :     0,                          /*tp_setattr*/
     140             :     0,                          /*tp_compare */
     141             :     0,                          /*tp_repr*/
     142             :     0,                          /*tp_as_number*/
     143             :     0,                          /*tp_as_sequence*/
     144             :     0,                          /*tp_as_mapping*/
     145             :     0,                          /*tp_hash */
     146             :     0,                          /*tp_call*/
     147             :     0,                          /*tp_str*/
     148             :     0,                          /*tp_getattro*/
     149             :     0,                          /*tp_setattro*/
     150             :     0,                          /*tp_as_buffer*/
     151             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
     152             :     PyDoc_STR("Exception raised when I/O would block "
     153             :               "on a non-blocking I/O stream"), /* tp_doc */
     154             :     0,                          /* tp_traverse */
     155             :     0,                          /* tp_clear */
     156             :     0,                          /* tp_richcompare */
     157             :     0,                          /* tp_weaklistoffset */
     158             :     0,                          /* tp_iter */
     159             :     0,                          /* tp_iternext */
     160             :     0,                          /* tp_methods */
     161             :     blockingioerror_members,    /* tp_members */
     162             :     0,                          /* tp_getset */
     163             :     0,                          /* tp_base */
     164             :     0,                          /* tp_dict */
     165             :     0,                          /* tp_descr_get */
     166             :     0,                          /* tp_descr_set */
     167             :     0,                          /* tp_dictoffset */
     168             :     (initproc)blockingioerror_init, /* tp_init */
     169             :     0,                          /* tp_alloc */
     170             :     0,                          /* tp_new */
     171             : };
     172             : PyObject *PyExc_BlockingIOError = (PyObject *)&_PyExc_BlockingIOError;
     173             : 
     174             : 
     175             : /*
     176             :  * The main open() function
     177             :  */
     178             : PyDoc_STRVAR(open_doc,
     179             : "Open file and return a stream.  Raise IOError upon failure.\n"
     180             : "\n"
     181             : "file is either a text or byte string giving the name (and the path\n"
     182             : "if the file isn't in the current working directory) of the file to\n"
     183             : "be opened or an integer file descriptor of the file to be\n"
     184             : "wrapped. (If a file descriptor is given, it is closed when the\n"
     185             : "returned I/O object is closed, unless closefd is set to False.)\n"
     186             : "\n"
     187             : "mode is an optional string that specifies the mode in which the file\n"
     188             : "is opened. It defaults to 'r' which means open for reading in text\n"
     189             : "mode.  Other common values are 'w' for writing (truncating the file if\n"
     190             : "it already exists), and 'a' for appending (which on some Unix systems,\n"
     191             : "means that all writes append to the end of the file regardless of the\n"
     192             : "current seek position). In text mode, if encoding is not specified the\n"
     193             : "encoding used is platform dependent. (For reading and writing raw\n"
     194             : "bytes use binary mode and leave encoding unspecified.) The available\n"
     195             : "modes are:\n"
     196             : "\n"
     197             : "========= ===============================================================\n"
     198             : "Character Meaning\n"
     199             : "--------- ---------------------------------------------------------------\n"
     200             : "'r'       open for reading (default)\n"
     201             : "'w'       open for writing, truncating the file first\n"
     202             : "'a'       open for writing, appending to the end of the file if it exists\n"
     203             : "'b'       binary mode\n"
     204             : "'t'       text mode (default)\n"
     205             : "'+'       open a disk file for updating (reading and writing)\n"
     206             : "'U'       universal newline mode (for backwards compatibility; unneeded\n"
     207             : "          for new code)\n"
     208             : "========= ===============================================================\n"
     209             : "\n"
     210             : "The default mode is 'rt' (open for reading text). For binary random\n"
     211             : "access, the mode 'w+b' opens and truncates the file to 0 bytes, while\n"
     212             : "'r+b' opens the file without truncation.\n"
     213             : "\n"
     214             : "Python distinguishes between files opened in binary and text modes,\n"
     215             : "even when the underlying operating system doesn't. Files opened in\n"
     216             : "binary mode (appending 'b' to the mode argument) return contents as\n"
     217             : "bytes objects without any decoding. In text mode (the default, or when\n"
     218             : "'t' is appended to the mode argument), the contents of the file are\n"
     219             : "returned as strings, the bytes having been first decoded using a\n"
     220             : "platform-dependent encoding or using the specified encoding if given.\n"
     221             : "\n"
     222             : "buffering is an optional integer used to set the buffering policy.\n"
     223             : "Pass 0 to switch buffering off (only allowed in binary mode), 1 to select\n"
     224             : "line buffering (only usable in text mode), and an integer > 1 to indicate\n"
     225             : "the size of a fixed-size chunk buffer.  When no buffering argument is\n"
     226             : "given, the default buffering policy works as follows:\n"
     227             : "\n"
     228             : "* Binary files are buffered in fixed-size chunks; the size of the buffer\n"
     229             : "  is chosen using a heuristic trying to determine the underlying device's\n"
     230             : "  \"block size\" and falling back on `io.DEFAULT_BUFFER_SIZE`.\n"
     231             : "  On many systems, the buffer will typically be 4096 or 8192 bytes long.\n"
     232             : "\n"
     233             : "* \"Interactive\" text files (files for which isatty() returns True)\n"
     234             : "  use line buffering.  Other text files use the policy described above\n"
     235             : "  for binary files.\n"
     236             : "\n"
     237             : "encoding is the name of the encoding used to decode or encode the\n"
     238             : "file. This should only be used in text mode. The default encoding is\n"
     239             : "platform dependent, but any encoding supported by Python can be\n"
     240             : "passed.  See the codecs module for the list of supported encodings.\n"
     241             : "\n"
     242             : "errors is an optional string that specifies how encoding errors are to\n"
     243             : "be handled---this argument should not be used in binary mode. Pass\n"
     244             : "'strict' to raise a ValueError exception if there is an encoding error\n"
     245             : "(the default of None has the same effect), or pass 'ignore' to ignore\n"
     246             : "errors. (Note that ignoring encoding errors can lead to data loss.)\n"
     247             : "See the documentation for codecs.register for a list of the permitted\n"
     248             : "encoding error strings.\n"
     249             : "\n"
     250             : "newline controls how universal newlines works (it only applies to text\n"
     251             : "mode). It can be None, '', '\\n', '\\r', and '\\r\\n'.  It works as\n"
     252             : "follows:\n"
     253             : "\n"
     254             : "* On input, if newline is None, universal newlines mode is\n"
     255             : "  enabled. Lines in the input can end in '\\n', '\\r', or '\\r\\n', and\n"
     256             : "  these are translated into '\\n' before being returned to the\n"
     257             : "  caller. If it is '', universal newline mode is enabled, but line\n"
     258             : "  endings are returned to the caller untranslated. If it has any of\n"
     259             : "  the other legal values, input lines are only terminated by the given\n"
     260             : "  string, and the line ending is returned to the caller untranslated.\n"
     261             : "\n"
     262             : "* On output, if newline is None, any '\\n' characters written are\n"
     263             : "  translated to the system default line separator, os.linesep. If\n"
     264             : "  newline is '', no translation takes place. If newline is any of the\n"
     265             : "  other legal values, any '\\n' characters written are translated to\n"
     266             : "  the given string.\n"
     267             : "\n"
     268             : "If closefd is False, the underlying file descriptor will be kept open\n"
     269             : "when the file is closed. This does not work when a file name is given\n"
     270             : "and must be True in that case.\n"
     271             : "\n"
     272             : "open() returns a file object whose type depends on the mode, and\n"
     273             : "through which the standard file operations such as reading and writing\n"
     274             : "are performed. When open() is used to open a file in a text mode ('w',\n"
     275             : "'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open\n"
     276             : "a file in a binary mode, the returned class varies: in read binary\n"
     277             : "mode, it returns a BufferedReader; in write binary and append binary\n"
     278             : "modes, it returns a BufferedWriter, and in read/write mode, it returns\n"
     279             : "a BufferedRandom.\n"
     280             : "\n"
     281             : "It is also possible to use a string or bytearray as a file for both\n"
     282             : "reading and writing. For strings StringIO can be used like a file\n"
     283             : "opened in a text mode, and for bytes a BytesIO can be used like a file\n"
     284             : "opened in a binary mode.\n"
     285             :     );
     286             : 
     287             : static PyObject *
     288           0 : io_open(PyObject *self, PyObject *args, PyObject *kwds)
     289             : {
     290           0 :     char *kwlist[] = {"file", "mode", "buffering",
     291             :                       "encoding", "errors", "newline",
     292             :                       "closefd", NULL};
     293             :     PyObject *file;
     294           0 :     char *mode = "r";
     295           0 :     int buffering = -1, closefd = 1;
     296           0 :     char *encoding = NULL, *errors = NULL, *newline = NULL;
     297             :     unsigned i;
     298             : 
     299           0 :     int reading = 0, writing = 0, appending = 0, updating = 0;
     300           0 :     int text = 0, binary = 0, universal = 0;
     301             : 
     302             :     char rawmode[5], *m;
     303             :     int line_buffering;
     304             :     long isatty;
     305             : 
     306           0 :     PyObject *raw, *modeobj = NULL, *buffer, *wrapper, *result = NULL;
     307             : 
     308           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|sizzzi:open", kwlist,
     309             :                                      &file, &mode, &buffering,
     310             :                                      &encoding, &errors, &newline,
     311             :                                      &closefd)) {
     312           0 :         return NULL;
     313             :     }
     314             : 
     315           0 :     if (!PyUnicode_Check(file) &&
     316           0 :         !PyBytes_Check(file) &&
     317           0 :         !PyNumber_Check(file)) {
     318           0 :         PyObject *repr = PyObject_Repr(file);
     319           0 :         if (repr != NULL) {
     320           0 :             PyErr_Format(PyExc_TypeError, "invalid file: %s",
     321           0 :                          PyString_AS_STRING(repr));
     322           0 :             Py_DECREF(repr);
     323             :         }
     324           0 :         return NULL;
     325             :     }
     326             : 
     327             :     /* Decode mode */
     328           0 :     for (i = 0; i < strlen(mode); i++) {
     329           0 :         char c = mode[i];
     330             : 
     331           0 :         switch (c) {
     332             :         case 'r':
     333           0 :             reading = 1;
     334           0 :             break;
     335             :         case 'w':
     336           0 :             writing = 1;
     337           0 :             break;
     338             :         case 'a':
     339           0 :             appending = 1;
     340           0 :             break;
     341             :         case '+':
     342           0 :             updating = 1;
     343           0 :             break;
     344             :         case 't':
     345           0 :             text = 1;
     346           0 :             break;
     347             :         case 'b':
     348           0 :             binary = 1;
     349           0 :             break;
     350             :         case 'U':
     351           0 :             universal = 1;
     352           0 :             reading = 1;
     353           0 :             break;
     354             :         default:
     355           0 :             goto invalid_mode;
     356             :         }
     357             : 
     358             :         /* c must not be duplicated */
     359           0 :         if (strchr(mode+i+1, c)) {
     360             :           invalid_mode:
     361           0 :             PyErr_Format(PyExc_ValueError, "invalid mode: '%s'", mode);
     362           0 :             return NULL;
     363             :         }
     364             : 
     365             :     }
     366             : 
     367           0 :     m = rawmode;
     368           0 :     if (reading)   *(m++) = 'r';
     369           0 :     if (writing)   *(m++) = 'w';
     370           0 :     if (appending) *(m++) = 'a';
     371           0 :     if (updating)  *(m++) = '+';
     372           0 :     *m = '\0';
     373             : 
     374             :     /* Parameters validation */
     375           0 :     if (universal) {
     376           0 :         if (writing || appending) {
     377           0 :             PyErr_SetString(PyExc_ValueError,
     378             :                             "can't use U and writing mode at once");
     379           0 :             return NULL;
     380             :         }
     381           0 :         reading = 1;
     382             :     }
     383             : 
     384           0 :     if (text && binary) {
     385           0 :         PyErr_SetString(PyExc_ValueError,
     386             :                         "can't have text and binary mode at once");
     387           0 :         return NULL;
     388             :     }
     389             : 
     390           0 :     if (reading + writing + appending > 1) {
     391           0 :         PyErr_SetString(PyExc_ValueError,
     392             :                         "must have exactly one of read/write/append mode");
     393           0 :         return NULL;
     394             :     }
     395             : 
     396           0 :     if (binary && encoding != NULL) {
     397           0 :         PyErr_SetString(PyExc_ValueError,
     398             :                         "binary mode doesn't take an encoding argument");
     399           0 :         return NULL;
     400             :     }
     401             : 
     402           0 :     if (binary && errors != NULL) {
     403           0 :         PyErr_SetString(PyExc_ValueError,
     404             :                         "binary mode doesn't take an errors argument");
     405           0 :         return NULL;
     406             :     }
     407             : 
     408           0 :     if (binary && newline != NULL) {
     409           0 :         PyErr_SetString(PyExc_ValueError,
     410             :                         "binary mode doesn't take a newline argument");
     411           0 :         return NULL;
     412             :     }
     413             : 
     414             :     /* Create the Raw file stream */
     415           0 :     raw = PyObject_CallFunction((PyObject *)&PyFileIO_Type,
     416             :                                 "Osi", file, rawmode, closefd);
     417           0 :     if (raw == NULL)
     418           0 :         return NULL;
     419           0 :     result = raw;
     420             : 
     421           0 :     modeobj = PyUnicode_FromString(mode);
     422           0 :     if (modeobj == NULL)
     423           0 :         goto error;
     424             : 
     425             :     /* buffering */
     426             :     {
     427           0 :         PyObject *res = PyObject_CallMethod(raw, "isatty", NULL);
     428           0 :         if (res == NULL)
     429           0 :             goto error;
     430           0 :         isatty = PyLong_AsLong(res);
     431           0 :         Py_DECREF(res);
     432           0 :         if (isatty == -1 && PyErr_Occurred())
     433           0 :             goto error;
     434             :     }
     435             : 
     436           0 :     if (buffering == 1 || (buffering < 0 && isatty)) {
     437           0 :         buffering = -1;
     438           0 :         line_buffering = 1;
     439             :     }
     440             :     else
     441           0 :         line_buffering = 0;
     442             : 
     443           0 :     if (buffering < 0) {
     444           0 :         buffering = DEFAULT_BUFFER_SIZE;
     445             : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
     446             :         {
     447             :             struct stat st;
     448             :             int fileno;
     449           0 :             PyObject *res = PyObject_CallMethod(raw, "fileno", NULL);
     450           0 :             if (res == NULL)
     451           0 :                 goto error;
     452             : 
     453           0 :             fileno = _PyInt_AsInt(res);
     454           0 :             Py_DECREF(res);
     455           0 :             if (fileno == -1 && PyErr_Occurred())
     456           0 :                 goto error;
     457             : 
     458           0 :             if (fstat(fileno, &st) >= 0 && st.st_blksize > 1)
     459           0 :                 buffering = st.st_blksize;
     460             :         }
     461             : #endif
     462             :     }
     463           0 :     if (buffering < 0) {
     464           0 :         PyErr_SetString(PyExc_ValueError,
     465             :                         "invalid buffering size");
     466           0 :         goto error;
     467             :     }
     468             : 
     469             :     /* if not buffering, returns the raw file object */
     470           0 :     if (buffering == 0) {
     471           0 :         if (!binary) {
     472           0 :             PyErr_SetString(PyExc_ValueError,
     473             :                             "can't have unbuffered text I/O");
     474           0 :             goto error;
     475             :         }
     476             : 
     477           0 :         Py_DECREF(modeobj);
     478           0 :         return result;
     479             :     }
     480             : 
     481             :     /* wraps into a buffered file */
     482             :     {
     483             :         PyObject *Buffered_class;
     484             : 
     485           0 :         if (updating)
     486           0 :             Buffered_class = (PyObject *)&PyBufferedRandom_Type;
     487           0 :         else if (writing || appending)
     488           0 :             Buffered_class = (PyObject *)&PyBufferedWriter_Type;
     489           0 :         else if (reading)
     490           0 :             Buffered_class = (PyObject *)&PyBufferedReader_Type;
     491             :         else {
     492           0 :             PyErr_Format(PyExc_ValueError,
     493             :                          "unknown mode: '%s'", mode);
     494           0 :             goto error;
     495             :         }
     496             : 
     497           0 :         buffer = PyObject_CallFunction(Buffered_class, "Oi", raw, buffering);
     498             :     }
     499           0 :     if (buffer == NULL)
     500           0 :         goto error;
     501           0 :     result = buffer;
     502           0 :     Py_DECREF(raw);
     503             : 
     504             : 
     505             :     /* if binary, returns the buffered file */
     506           0 :     if (binary) {
     507           0 :         Py_DECREF(modeobj);
     508           0 :         return result;
     509             :     }
     510             : 
     511             :     /* wraps into a TextIOWrapper */
     512           0 :     wrapper = PyObject_CallFunction((PyObject *)&PyTextIOWrapper_Type,
     513             :                                     "Osssi",
     514             :                                     buffer,
     515             :                                     encoding, errors, newline,
     516             :                                     line_buffering);
     517           0 :     if (wrapper == NULL)
     518           0 :         goto error;
     519           0 :     result = wrapper;
     520           0 :     Py_DECREF(buffer);
     521             : 
     522           0 :     if (PyObject_SetAttrString(wrapper, "mode", modeobj) < 0)
     523           0 :         goto error;
     524           0 :     Py_DECREF(modeobj);
     525           0 :     return result;
     526             : 
     527             :   error:
     528           0 :     if (result != NULL) {
     529             :         PyObject *exc, *val, *tb, *close_result;
     530           0 :         PyErr_Fetch(&exc, &val, &tb);
     531           0 :         close_result = PyObject_CallMethod(result, "close", NULL);
     532           0 :         _PyErr_ReplaceException(exc, val, tb);
     533           0 :         Py_XDECREF(close_result);
     534           0 :         Py_DECREF(result);
     535             :     }
     536           0 :     Py_XDECREF(modeobj);
     537           0 :     return NULL;
     538             : }
     539             : 
     540             : /*
     541             :  * Private helpers for the io module.
     542             :  */
     543             : 
     544             : Py_off_t
     545           0 : PyNumber_AsOff_t(PyObject *item, PyObject *err)
     546             : {
     547             :     Py_off_t result;
     548             :     PyObject *runerr;
     549           0 :     PyObject *value = PyNumber_Index(item);
     550           0 :     if (value == NULL)
     551           0 :         return -1;
     552             : 
     553           0 :     if (PyInt_Check(value)) {
     554             :         /* We assume a long always fits in a Py_off_t... */
     555           0 :         result = (Py_off_t) PyInt_AS_LONG(value);
     556           0 :         goto finish;
     557             :     }
     558             : 
     559             :     /* We're done if PyLong_AsSsize_t() returns without error. */
     560           0 :     result = PyLong_AsOff_t(value);
     561           0 :     if (result != -1 || !(runerr = PyErr_Occurred()))
     562             :         goto finish;
     563             : 
     564             :     /* Error handling code -- only manage OverflowError differently */
     565           0 :     if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError))
     566           0 :         goto finish;
     567             : 
     568           0 :     PyErr_Clear();
     569             :     /* If no error-handling desired then the default clipping
     570             :        is sufficient.
     571             :      */
     572           0 :     if (!err) {
     573             :         assert(PyLong_Check(value));
     574             :         /* Whether or not it is less than or equal to
     575             :            zero is determined by the sign of ob_size
     576             :         */
     577           0 :         if (_PyLong_Sign(value) < 0)
     578           0 :             result = PY_OFF_T_MIN;
     579             :         else
     580           0 :             result = PY_OFF_T_MAX;
     581             :     }
     582             :     else {
     583             :         /* Otherwise replace the error with caller's error object. */
     584           0 :         PyErr_Format(err,
     585             :                      "cannot fit '%.200s' into an offset-sized integer",
     586           0 :                      item->ob_type->tp_name);
     587             :     }
     588             : 
     589             :  finish:
     590           0 :     Py_DECREF(value);
     591           0 :     return result;
     592             : }
     593             : 
     594             : 
     595             : /* Basically the "n" format code with the ability to turn None into -1. */
     596             : int 
     597           0 : _PyIO_ConvertSsize_t(PyObject *obj, void *result) {
     598             :     Py_ssize_t limit;
     599           0 :     if (obj == Py_None) {
     600           0 :         limit = -1;
     601             :     }
     602           0 :     else if (PyNumber_Check(obj)) {
     603           0 :         limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
     604           0 :         if (limit == -1 && PyErr_Occurred())
     605           0 :             return 0;
     606             :     }
     607             :     else {
     608           0 :         PyErr_Format(PyExc_TypeError,
     609             :                      "integer argument expected, got '%.200s'",
     610           0 :                      Py_TYPE(obj)->tp_name);
     611           0 :         return 0;
     612             :     }
     613           0 :     *((Py_ssize_t *)result) = limit;
     614           0 :     return 1;
     615             : }
     616             : 
     617             : 
     618             : /*
     619             :  * Module definition
     620             :  */
     621             : 
     622             : PyObject *_PyIO_os_module = NULL;
     623             : PyObject *_PyIO_locale_module = NULL;
     624             : PyObject *_PyIO_unsupported_operation = NULL;
     625             : 
     626             : static PyMethodDef module_methods[] = {
     627             :     {"open", (PyCFunction)io_open, METH_VARARGS|METH_KEYWORDS, open_doc},
     628             :     {NULL, NULL}
     629             : };
     630             : 
     631             : PyMODINIT_FUNC
     632           3 : init_io(void)
     633             : {
     634           3 :     PyObject *m = Py_InitModule4("_io", module_methods,
     635             :                                  module_doc, NULL, PYTHON_API_VERSION);
     636           3 :     if (m == NULL)
     637           0 :         return;
     638             : 
     639             :     /* put os in the module state */
     640           3 :     _PyIO_os_module = PyImport_ImportModule("os");
     641           3 :     if (_PyIO_os_module == NULL)
     642           0 :         goto fail;
     643             : 
     644             : #define ADD_TYPE(type, name) \
     645             :     if (PyType_Ready(type) < 0) \
     646             :         goto fail; \
     647             :     Py_INCREF(type); \
     648             :     if (PyModule_AddObject(m, name, (PyObject *)type) < 0) {  \
     649             :         Py_DECREF(type); \
     650             :         goto fail; \
     651             :     }
     652             : 
     653             :     /* DEFAULT_BUFFER_SIZE */
     654           3 :     if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0)
     655           0 :         goto fail;
     656             : 
     657             :     /* UnsupportedOperation inherits from ValueError and IOError */
     658           3 :     _PyIO_unsupported_operation = PyObject_CallFunction(
     659             :         (PyObject *)&PyType_Type, "s(OO){}",
     660             :         "UnsupportedOperation", PyExc_ValueError, PyExc_IOError);
     661           3 :     if (_PyIO_unsupported_operation == NULL)
     662           0 :         goto fail;
     663           3 :     Py_INCREF(_PyIO_unsupported_operation);
     664           3 :     if (PyModule_AddObject(m, "UnsupportedOperation",
     665             :                            _PyIO_unsupported_operation) < 0)
     666           0 :         goto fail;
     667             : 
     668             :     /* BlockingIOError */
     669           3 :     _PyExc_BlockingIOError.tp_base = (PyTypeObject *) PyExc_IOError;
     670           3 :     ADD_TYPE(&_PyExc_BlockingIOError, "BlockingIOError");
     671             : 
     672             :     /* Concrete base types of the IO ABCs.
     673             :        (the ABCs themselves are declared through inheritance in io.py)
     674             :     */
     675           3 :     ADD_TYPE(&PyIOBase_Type, "_IOBase");
     676           3 :     ADD_TYPE(&PyRawIOBase_Type, "_RawIOBase");
     677           3 :     ADD_TYPE(&PyBufferedIOBase_Type, "_BufferedIOBase");
     678           3 :     ADD_TYPE(&PyTextIOBase_Type, "_TextIOBase");
     679             : 
     680             :     /* Implementation of concrete IO objects. */
     681             :     /* FileIO */
     682           3 :     PyFileIO_Type.tp_base = &PyRawIOBase_Type;
     683           3 :     ADD_TYPE(&PyFileIO_Type, "FileIO");
     684             : 
     685             :     /* BytesIO */
     686           3 :     PyBytesIO_Type.tp_base = &PyBufferedIOBase_Type;
     687           3 :     ADD_TYPE(&PyBytesIO_Type, "BytesIO");
     688             : 
     689             :     /* StringIO */
     690           3 :     PyStringIO_Type.tp_base = &PyTextIOBase_Type;
     691           3 :     ADD_TYPE(&PyStringIO_Type, "StringIO");
     692             : 
     693             :     /* BufferedReader */
     694           3 :     PyBufferedReader_Type.tp_base = &PyBufferedIOBase_Type;
     695           3 :     ADD_TYPE(&PyBufferedReader_Type, "BufferedReader");
     696             : 
     697             :     /* BufferedWriter */
     698           3 :     PyBufferedWriter_Type.tp_base = &PyBufferedIOBase_Type;
     699           3 :     ADD_TYPE(&PyBufferedWriter_Type, "BufferedWriter");
     700             : 
     701             :     /* BufferedRWPair */
     702           3 :     PyBufferedRWPair_Type.tp_base = &PyBufferedIOBase_Type;
     703           3 :     ADD_TYPE(&PyBufferedRWPair_Type, "BufferedRWPair");
     704             : 
     705             :     /* BufferedRandom */
     706           3 :     PyBufferedRandom_Type.tp_base = &PyBufferedIOBase_Type;
     707           3 :     ADD_TYPE(&PyBufferedRandom_Type, "BufferedRandom");
     708             : 
     709             :     /* TextIOWrapper */
     710           3 :     PyTextIOWrapper_Type.tp_base = &PyTextIOBase_Type;
     711           3 :     ADD_TYPE(&PyTextIOWrapper_Type, "TextIOWrapper");
     712             : 
     713             :     /* IncrementalNewlineDecoder */
     714           3 :     ADD_TYPE(&PyIncrementalNewlineDecoder_Type, "IncrementalNewlineDecoder");
     715             : 
     716             :     /* Interned strings */
     717           3 :     if (!(_PyIO_str_close = PyString_InternFromString("close")))
     718           0 :         goto fail;
     719           3 :     if (!(_PyIO_str_closed = PyString_InternFromString("closed")))
     720           0 :         goto fail;
     721           3 :     if (!(_PyIO_str_decode = PyString_InternFromString("decode")))
     722           0 :         goto fail;
     723           3 :     if (!(_PyIO_str_encode = PyString_InternFromString("encode")))
     724           0 :         goto fail;
     725           3 :     if (!(_PyIO_str_fileno = PyString_InternFromString("fileno")))
     726           0 :         goto fail;
     727           3 :     if (!(_PyIO_str_flush = PyString_InternFromString("flush")))
     728           0 :         goto fail;
     729           3 :     if (!(_PyIO_str_getstate = PyString_InternFromString("getstate")))
     730           0 :         goto fail;
     731           3 :     if (!(_PyIO_str_isatty = PyString_InternFromString("isatty")))
     732           0 :         goto fail;
     733           3 :     if (!(_PyIO_str_newlines = PyString_InternFromString("newlines")))
     734           0 :         goto fail;
     735           3 :     if (!(_PyIO_str_nl = PyString_InternFromString("\n")))
     736           0 :         goto fail;
     737           3 :     if (!(_PyIO_str_read = PyString_InternFromString("read")))
     738           0 :         goto fail;
     739           3 :     if (!(_PyIO_str_read1 = PyString_InternFromString("read1")))
     740           0 :         goto fail;
     741           3 :     if (!(_PyIO_str_readable = PyString_InternFromString("readable")))
     742           0 :         goto fail;
     743           3 :     if (!(_PyIO_str_readinto = PyString_InternFromString("readinto")))
     744           0 :         goto fail;
     745           3 :     if (!(_PyIO_str_readline = PyString_InternFromString("readline")))
     746           0 :         goto fail;
     747           3 :     if (!(_PyIO_str_reset = PyString_InternFromString("reset")))
     748           0 :         goto fail;
     749           3 :     if (!(_PyIO_str_seek = PyString_InternFromString("seek")))
     750           0 :         goto fail;
     751           3 :     if (!(_PyIO_str_seekable = PyString_InternFromString("seekable")))
     752           0 :         goto fail;
     753           3 :     if (!(_PyIO_str_setstate = PyString_InternFromString("setstate")))
     754           0 :         goto fail;
     755           3 :     if (!(_PyIO_str_tell = PyString_InternFromString("tell")))
     756           0 :         goto fail;
     757           3 :     if (!(_PyIO_str_truncate = PyString_InternFromString("truncate")))
     758           0 :         goto fail;
     759           3 :     if (!(_PyIO_str_write = PyString_InternFromString("write")))
     760           0 :         goto fail;
     761           3 :     if (!(_PyIO_str_writable = PyString_InternFromString("writable")))
     762           0 :         goto fail;
     763             :     
     764           3 :     if (!(_PyIO_empty_str = PyUnicode_FromStringAndSize(NULL, 0)))
     765           0 :         goto fail;
     766           3 :     if (!(_PyIO_empty_bytes = PyBytes_FromStringAndSize(NULL, 0)))
     767           0 :         goto fail;
     768           3 :     if (!(_PyIO_zero = PyLong_FromLong(0L)))
     769           0 :         goto fail;
     770             : 
     771           3 :     return;
     772             : 
     773             :   fail:
     774           0 :     Py_CLEAR(_PyIO_os_module);
     775           0 :     Py_CLEAR(_PyIO_unsupported_operation);
     776           0 :     Py_DECREF(m);
     777             : }

Generated by: LCOV version 1.10