diff options
Diffstat (limited to 'Modules/_io/_iomodule.c')
-rw-r--r-- | Modules/_io/_iomodule.c | 306 |
1 files changed, 148 insertions, 158 deletions
diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 45c31a5..528bcd4 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -93,140 +93,145 @@ PyDoc_STRVAR(module_doc, /* * The main open() function */ -PyDoc_STRVAR(open_doc, -"open(file, mode='r', buffering=-1, encoding=None,\n" -" errors=None, newline=None, closefd=True, opener=None) -> file object\n" -"\n" -"Open file and return a stream. Raise IOError upon failure.\n" -"\n" -"file is either a text or byte string giving the name (and the path\n" -"if the file isn't in the current working directory) of the file to\n" -"be opened or an integer file descriptor of the file to be\n" -"wrapped. (If a file descriptor is given, it is closed when the\n" -"returned I/O object is closed, unless closefd is set to False.)\n" -"\n" -"mode is an optional string that specifies the mode in which the file\n" -"is opened. It defaults to 'r' which means open for reading in text\n" -"mode. Other common values are 'w' for writing (truncating the file if\n" -"it already exists), 'x' for creating and writing to a new file, and\n" -"'a' for appending (which on some Unix systems, means that all writes\n" -"append to the end of the file regardless of the current seek position).\n" -"In text mode, if encoding is not specified the encoding used is platform\n" -"dependent: locale.getpreferredencoding(False) is called to get the\n" -"current locale encoding. (For reading and writing raw bytes use binary\n" -"mode and leave encoding unspecified.) The available modes are:\n" -"\n" -"========= ===============================================================\n" -"Character Meaning\n" -"--------- ---------------------------------------------------------------\n" -"'r' open for reading (default)\n" -"'w' open for writing, truncating the file first\n" -"'x' create a new file and open it for writing\n" -"'a' open for writing, appending to the end of the file if it exists\n" -"'b' binary mode\n" -"'t' text mode (default)\n" -"'+' open a disk file for updating (reading and writing)\n" -"'U' universal newline mode (deprecated)\n" -"========= ===============================================================\n" -"\n" -"The default mode is 'rt' (open for reading text). For binary random\n" -"access, the mode 'w+b' opens and truncates the file to 0 bytes, while\n" -"'r+b' opens the file without truncation. The 'x' mode implies 'w' and\n" -"raises an `FileExistsError` if the file already exists.\n" -"\n" -"Python distinguishes between files opened in binary and text modes,\n" -"even when the underlying operating system doesn't. Files opened in\n" -"binary mode (appending 'b' to the mode argument) return contents as\n" -"bytes objects without any decoding. In text mode (the default, or when\n" -"'t' is appended to the mode argument), the contents of the file are\n" -"returned as strings, the bytes having been first decoded using a\n" -"platform-dependent encoding or using the specified encoding if given.\n" -"\n" -"'U' mode is deprecated and will raise an exception in future versions\n" -"of Python. It has no effect in Python 3. Use newline to control\n" -"universal newlines mode.\n" -"\n" -"buffering is an optional integer used to set the buffering policy.\n" -"Pass 0 to switch buffering off (only allowed in binary mode), 1 to select\n" -"line buffering (only usable in text mode), and an integer > 1 to indicate\n" -"the size of a fixed-size chunk buffer. When no buffering argument is\n" -"given, the default buffering policy works as follows:\n" -"\n" -"* Binary files are buffered in fixed-size chunks; the size of the buffer\n" -" is chosen using a heuristic trying to determine the underlying device's\n" -" \"block size\" and falling back on `io.DEFAULT_BUFFER_SIZE`.\n" -" On many systems, the buffer will typically be 4096 or 8192 bytes long.\n" -"\n" -"* \"Interactive\" text files (files for which isatty() returns True)\n" -" use line buffering. Other text files use the policy described above\n" -" for binary files.\n" -"\n" -"encoding is the name of the encoding used to decode or encode the\n" -"file. This should only be used in text mode. The default encoding is\n" -"platform dependent, but any encoding supported by Python can be\n" -"passed. See the codecs module for the list of supported encodings.\n" -"\n" -"errors is an optional string that specifies how encoding errors are to\n" -"be handled---this argument should not be used in binary mode. Pass\n" -"'strict' to raise a ValueError exception if there is an encoding error\n" -"(the default of None has the same effect), or pass 'ignore' to ignore\n" -"errors. (Note that ignoring encoding errors can lead to data loss.)\n" -"See the documentation for codecs.register or run 'help(codecs.Codec)'\n" -"for a list of the permitted encoding error strings.\n" -"\n" -"newline controls how universal newlines works (it only applies to text\n" -"mode). It can be None, '', '\\n', '\\r', and '\\r\\n'. It works as\n" -"follows:\n" -"\n" -"* On input, if newline is None, universal newlines mode is\n" -" enabled. Lines in the input can end in '\\n', '\\r', or '\\r\\n', and\n" -" these are translated into '\\n' before being returned to the\n" -" caller. If it is '', universal newline mode is enabled, but line\n" -" endings are returned to the caller untranslated. If it has any of\n" -" the other legal values, input lines are only terminated by the given\n" -" string, and the line ending is returned to the caller untranslated.\n" -"\n" -"* On output, if newline is None, any '\\n' characters written are\n" -" translated to the system default line separator, os.linesep. If\n" -" newline is '' or '\\n', no translation takes place. If newline is any\n" -" of the other legal values, any '\\n' characters written are translated\n" -" to the given string.\n" -"\n" -"If closefd is False, the underlying file descriptor will be kept open\n" -"when the file is closed. This does not work when a file name is given\n" -"and must be True in that case.\n" -"\n" -"A custom opener can be used by passing a callable as *opener*. The\n" -"underlying file descriptor for the file object is then obtained by\n" -"calling *opener* with (*file*, *flags*). *opener* must return an open\n" -"file descriptor (passing os.open as *opener* results in functionality\n" -"similar to passing None).\n" -"\n" -"open() returns a file object whose type depends on the mode, and\n" -"through which the standard file operations such as reading and writing\n" -"are performed. When open() is used to open a file in a text mode ('w',\n" -"'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open\n" -"a file in a binary mode, the returned class varies: in read binary\n" -"mode, it returns a BufferedReader; in write binary and append binary\n" -"modes, it returns a BufferedWriter, and in read/write mode, it returns\n" -"a BufferedRandom.\n" -"\n" -"It is also possible to use a string or bytearray as a file for both\n" -"reading and writing. For strings StringIO can be used like a file\n" -"opened in a text mode, and for bytes a BytesIO can be used like a file\n" -"opened in a binary mode.\n" - ); +/*[clinic input] +module _io + +_io.open + file: object + mode: str = "r" + buffering: int = -1 + encoding: str(accept={str, NoneType}) = NULL + errors: str(accept={str, NoneType}) = NULL + newline: str(accept={str, NoneType}) = NULL + closefd: int(c_default="1") = True + opener: object = None + +Open file and return a stream. Raise IOError upon failure. + +file is either a text or byte string giving the name (and the path +if the file isn't in the current working directory) of the file to +be opened or an integer file descriptor of the file to be +wrapped. (If a file descriptor is given, it is closed when the +returned I/O object is closed, unless closefd is set to False.) + +mode is an optional string that specifies the mode in which the file +is opened. It defaults to 'r' which means open for reading in text +mode. Other common values are 'w' for writing (truncating the file if +it already exists), 'x' for creating and writing to a new file, and +'a' for appending (which on some Unix systems, means that all writes +append to the end of the file regardless of the current seek position). +In text mode, if encoding is not specified the encoding used is platform +dependent: locale.getpreferredencoding(False) is called to get the +current locale encoding. (For reading and writing raw bytes use binary +mode and leave encoding unspecified.) The available modes are: + +========= =============================================================== +Character Meaning +--------- --------------------------------------------------------------- +'r' open for reading (default) +'w' open for writing, truncating the file first +'x' create a new file and open it for writing +'a' open for writing, appending to the end of the file if it exists +'b' binary mode +'t' text mode (default) +'+' open a disk file for updating (reading and writing) +'U' universal newline mode (deprecated) +========= =============================================================== + +The default mode is 'rt' (open for reading text). For binary random +access, the mode 'w+b' opens and truncates the file to 0 bytes, while +'r+b' opens the file without truncation. The 'x' mode implies 'w' and +raises an `FileExistsError` if the file already exists. + +Python distinguishes between files opened in binary and text modes, +even when the underlying operating system doesn't. Files opened in +binary mode (appending 'b' to the mode argument) return contents as +bytes objects without any decoding. In text mode (the default, or when +'t' is appended to the mode argument), the contents of the file are +returned as strings, the bytes having been first decoded using a +platform-dependent encoding or using the specified encoding if given. + +'U' mode is deprecated and will raise an exception in future versions +of Python. It has no effect in Python 3. Use newline to control +universal newlines mode. + +buffering is an optional integer used to set the buffering policy. +Pass 0 to switch buffering off (only allowed in binary mode), 1 to select +line buffering (only usable in text mode), and an integer > 1 to indicate +the size of a fixed-size chunk buffer. When no buffering argument is +given, the default buffering policy works as follows: + +* Binary files are buffered in fixed-size chunks; the size of the buffer + is chosen using a heuristic trying to determine the underlying device's + "block size" and falling back on `io.DEFAULT_BUFFER_SIZE`. + On many systems, the buffer will typically be 4096 or 8192 bytes long. + +* "Interactive" text files (files for which isatty() returns True) + use line buffering. Other text files use the policy described above + for binary files. + +encoding is the name of the encoding used to decode or encode the +file. This should only be used in text mode. The default encoding is +platform dependent, but any encoding supported by Python can be +passed. See the codecs module for the list of supported encodings. + +errors is an optional string that specifies how encoding errors are to +be handled---this argument should not be used in binary mode. Pass +'strict' to raise a ValueError exception if there is an encoding error +(the default of None has the same effect), or pass 'ignore' to ignore +errors. (Note that ignoring encoding errors can lead to data loss.) +See the documentation for codecs.register or run 'help(codecs.Codec)' +for a list of the permitted encoding error strings. + +newline controls how universal newlines works (it only applies to text +mode). It can be None, '', '\n', '\r', and '\r\n'. It works as +follows: + +* On input, if newline is None, universal newlines mode is + enabled. Lines in the input can end in '\n', '\r', or '\r\n', and + these are translated into '\n' before being returned to the + caller. If it is '', universal newline mode is enabled, but line + endings are returned to the caller untranslated. If it has any of + the other legal values, input lines are only terminated by the given + string, and the line ending is returned to the caller untranslated. + +* On output, if newline is None, any '\n' characters written are + translated to the system default line separator, os.linesep. If + newline is '' or '\n', no translation takes place. If newline is any + of the other legal values, any '\n' characters written are translated + to the given string. + +If closefd is False, the underlying file descriptor will be kept open +when the file is closed. This does not work when a file name is given +and must be True in that case. + +A custom opener can be used by passing a callable as *opener*. The +underlying file descriptor for the file object is then obtained by +calling *opener* with (*file*, *flags*). *opener* must return an open +file descriptor (passing os.open as *opener* results in functionality +similar to passing None). + +open() returns a file object whose type depends on the mode, and +through which the standard file operations such as reading and writing +are performed. When open() is used to open a file in a text mode ('w', +'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open +a file in a binary mode, the returned class varies: in read binary +mode, it returns a BufferedReader; in write binary and append binary +modes, it returns a BufferedWriter, and in read/write mode, it returns +a BufferedRandom. + +It is also possible to use a string or bytearray as a file for both +reading and writing. For strings StringIO can be used like a file +opened in a text mode, and for bytes a BytesIO can be used like a file +opened in a binary mode. +[clinic start generated code]*/ static PyObject * -io_open(PyObject *self, PyObject *args, PyObject *kwds) +_io_open_impl(PyModuleDef *module, PyObject *file, const char *mode, + int buffering, const char *encoding, const char *errors, + const char *newline, int closefd, PyObject *opener) +/*[clinic end generated code: output=7615d0d746eb14d2 input=f4e1ca75223987bc]*/ { - char *kwlist[] = {"file", "mode", "buffering", - "encoding", "errors", "newline", - "closefd", "opener", NULL}; - PyObject *file, *opener = Py_None; - char *mode = "r"; - int buffering = -1, closefd = 1; - char *encoding = NULL, *errors = NULL, *newline = NULL; unsigned i; int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0; @@ -237,18 +242,11 @@ io_open(PyObject *self, PyObject *args, PyObject *kwds) PyObject *raw, *modeobj = NULL, *buffer, *wrapper, *result = NULL; + _Py_IDENTIFIER(_blksize); _Py_IDENTIFIER(isatty); - _Py_IDENTIFIER(fileno); _Py_IDENTIFIER(mode); _Py_IDENTIFIER(close); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|sizzziO:open", kwlist, - &file, &mode, &buffering, - &encoding, &errors, &newline, - &closefd, &opener)) { - return NULL; - } - if (!PyUnicode_Check(file) && !PyBytes_Check(file) && !PyNumber_Check(file)) { @@ -380,24 +378,14 @@ io_open(PyObject *self, PyObject *args, PyObject *kwds) line_buffering = 0; if (buffering < 0) { - buffering = DEFAULT_BUFFER_SIZE; -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - { - struct stat st; - long fileno; - PyObject *res = _PyObject_CallMethodId(raw, &PyId_fileno, NULL); - if (res == NULL) - goto error; - - fileno = PyLong_AsLong(res); - Py_DECREF(res); - if (fileno == -1 && PyErr_Occurred()) - goto error; - - if (fstat(fileno, &st) >= 0 && st.st_blksize > 1) - buffering = st.st_blksize; - } -#endif + PyObject *blksize_obj; + blksize_obj = _PyObject_GetAttrId(raw, &PyId__blksize); + if (blksize_obj == NULL) + goto error; + buffering = PyLong_AsLong(blksize_obj); + Py_DECREF(blksize_obj); + if (buffering == -1 && PyErr_Occurred()) + goto error; } if (buffering < 0) { PyErr_SetString(PyExc_ValueError, @@ -621,8 +609,10 @@ iomodule_free(PyObject *mod) { * Module definition */ +#include "clinic/_iomodule.c.h" + static PyMethodDef module_methods[] = { - {"open", (PyCFunction)io_open, METH_VARARGS|METH_KEYWORDS, open_doc}, + _IO_OPEN_METHODDEF {NULL, NULL} }; |