summaryrefslogtreecommitdiff
path: root/Modules/_io
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_io')
-rw-r--r--Modules/_io/_iomodule.c306
-rw-r--r--Modules/_io/_iomodule.h2
-rw-r--r--Modules/_io/bufferedio.c1023
-rw-r--r--Modules/_io/bytesio.c661
-rw-r--r--Modules/_io/clinic/_iomodule.c.h159
-rw-r--r--Modules/_io/clinic/bufferedio.c.h454
-rw-r--r--Modules/_io/clinic/bytesio.c.h422
-rw-r--r--Modules/_io/clinic/fileio.c.h367
-rw-r--r--Modules/_io/clinic/iobase.c.h279
-rw-r--r--Modules/_io/clinic/stringio.c.h286
-rw-r--r--Modules/_io/clinic/textio.c.h456
-rw-r--r--Modules/_io/fileio.c650
-rw-r--r--Modules/_io/iobase.c264
-rw-r--r--Modules/_io/stringio.c269
-rw-r--r--Modules/_io/textio.c539
15 files changed, 4474 insertions, 1663 deletions
diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c
index 45c31a550e..528bcd4ac1 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}
};
diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h
index 8927864e8c..9d5205ec30 100644
--- a/Modules/_io/_iomodule.h
+++ b/Modules/_io/_iomodule.h
@@ -69,7 +69,7 @@ extern int _PyIO_trap_eintr(void);
* Offset type for positioning.
*/
-/* Printing a variable of type off_t (with e.g., PyString_FromFormat)
+/* Printing a variable of type off_t (with e.g., PyUnicode_FromFormat)
correctly and without producing compiler warnings is surprisingly painful.
We identify an integer type whose size matches off_t and then: (1) cast the
off_t to that integer type and (2) use the appropriate conversion
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index 365bb85c74..29e000bde4 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -13,6 +13,24 @@
#include "pythread.h"
#include "_iomodule.h"
+/*[clinic input]
+module _io
+class _io._BufferedIOBase "PyObject *" "&PyBufferedIOBase_Type"
+class _io._Buffered "buffered *" "&PyBufferedIOBase_Type"
+class _io.BufferedReader "buffered *" "&PyBufferedReader_Type"
+class _io.BufferedWriter "buffered *" "&PyBufferedWriter_Type"
+class _io.BufferedRWPair "rwpair *" "&PyBufferedRWPair_Type"
+class _io.BufferedRandom "buffered *" "&PyBufferedRandom_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=59460b9c5639984d]*/
+
+/*[python input]
+class io_ssize_t_converter(CConverter):
+ type = 'Py_ssize_t'
+ converter = '_PyIO_ConvertSsize_t'
+[python start generated code]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/
+
_Py_IDENTIFIER(close);
_Py_IDENTIFIER(_dealloc_warn);
_Py_IDENTIFIER(flush);
@@ -24,6 +42,7 @@ _Py_IDENTIFIER(read);
_Py_IDENTIFIER(read1);
_Py_IDENTIFIER(readable);
_Py_IDENTIFIER(readinto);
+_Py_IDENTIFIER(readinto1);
_Py_IDENTIFIER(writable);
_Py_IDENTIFIER(write);
@@ -47,45 +66,63 @@ PyDoc_STRVAR(bufferediobase_doc,
);
static PyObject *
-bufferediobase_readinto(PyObject *self, PyObject *args)
+_bufferediobase_readinto_generic(PyObject *self, Py_buffer *buffer, char readinto1)
{
- Py_buffer buf;
Py_ssize_t len;
PyObject *data;
- if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
- return NULL;
- }
-
- data = _PyObject_CallMethodId(self, &PyId_read, "n", buf.len);
+ data = _PyObject_CallMethodId(self,
+ readinto1 ? &PyId_read1 : &PyId_read,
+ "n", buffer->len);
if (data == NULL)
- goto error;
+ return NULL;
if (!PyBytes_Check(data)) {
Py_DECREF(data);
PyErr_SetString(PyExc_TypeError, "read() should return bytes");
- goto error;
+ return NULL;
}
len = Py_SIZE(data);
- if (len > buf.len) {
+ if (len > buffer->len) {
PyErr_Format(PyExc_ValueError,
"read() returned too much data: "
"%zd bytes requested, %zd returned",
- buf.len, len);
+ buffer->len, len);
Py_DECREF(data);
- goto error;
+ return NULL;
}
- memcpy(buf.buf, PyBytes_AS_STRING(data), len);
+ memcpy(buffer->buf, PyBytes_AS_STRING(data), len);
- PyBuffer_Release(&buf);
Py_DECREF(data);
return PyLong_FromSsize_t(len);
+}
- error:
- PyBuffer_Release(&buf);
- return NULL;
+/*[clinic input]
+_io._BufferedIOBase.readinto
+ buffer: Py_buffer(accept={rwbuffer})
+ /
+[clinic start generated code]*/
+
+static PyObject *
+_io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer)
+/*[clinic end generated code: output=8c8cda6684af8038 input=00a6b9a38f29830a]*/
+{
+ return _bufferediobase_readinto_generic(self, buffer, 0);
+}
+
+/*[clinic input]
+_io._BufferedIOBase.readinto1
+ buffer: Py_buffer(accept={rwbuffer})
+ /
+[clinic start generated code]*/
+
+static PyObject *
+_io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer)
+/*[clinic end generated code: output=358623e4fd2b69d3 input=ebad75b4aadfb9be]*/
+{
+ return _bufferediobase_readinto_generic(self, buffer, 1);
}
static PyObject *
@@ -97,14 +134,18 @@ bufferediobase_unsupported(const char *message)
return NULL;
}
-PyDoc_STRVAR(bufferediobase_detach_doc,
- "Disconnect this buffer from its underlying raw stream and return it.\n"
- "\n"
- "After the raw stream has been detached, the buffer is in an unusable\n"
- "state.\n");
+/*[clinic input]
+_io._BufferedIOBase.detach
+
+Disconnect this buffer from its underlying raw stream and return it.
+
+After the raw stream has been detached, the buffer is in an unusable
+state.
+[clinic start generated code]*/
static PyObject *
-bufferediobase_detach(PyObject *self)
+_io__BufferedIOBase_detach_impl(PyObject *self)
+/*[clinic end generated code: output=754977c8d10ed88c input=822427fb58fe4169]*/
{
return bufferediobase_unsupported("detach");
}
@@ -162,68 +203,6 @@ bufferediobase_write(PyObject *self, PyObject *args)
}
-static PyMethodDef bufferediobase_methods[] = {
- {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc},
- {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
- {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
- {"readinto", bufferediobase_readinto, METH_VARARGS, NULL},
- {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
- {NULL, NULL}
-};
-
-PyTypeObject PyBufferedIOBase_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io._BufferedIOBase", /*tp_name*/
- 0, /*tp_basicsize*/
- 0, /*tp_itemsize*/
- 0, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare */
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
- | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
- bufferediobase_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- bufferediobase_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &PyIOBase_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- 0, /* tp_del */
- 0, /* tp_version_tag */
- 0, /* tp_finalize */
-};
-
-
typedef struct {
PyObject_HEAD
@@ -318,7 +297,7 @@ _enter_buffered_busy(buffered *self)
* Note that non-daemon threads have already exited here, so this
* shouldn't affect carefully written threaded I/O code.
*/
- st = PyThread_acquire_lock_timed(self->lock, 1e6, 0);
+ st = PyThread_acquire_lock_timed(self->lock, (PY_TIMEOUT_T)1e6, 0);
}
Py_END_ALLOW_THREADS
if (relax_locking && st != PY_LOCK_ACQUIRED) {
@@ -683,11 +662,7 @@ static void
_set_BlockingIOError(char *msg, Py_ssize_t written)
{
PyObject *err;
-#ifdef Py_DEBUG
- /* in debug mode, PyEval_EvalFrameEx() fails with an assertion error
- if an exception is set when it is called */
PyErr_Clear();
-#endif
err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
errno, msg, written);
if (err)
@@ -882,19 +857,22 @@ buffered_flush(buffered *self, PyObject *args)
return res;
}
+/*[clinic input]
+_io._Buffered.peek
+ size: Py_ssize_t = 0
+ /
+
+[clinic start generated code]*/
+
static PyObject *
-buffered_peek(buffered *self, PyObject *args)
+_io__Buffered_peek_impl(buffered *self, Py_ssize_t size)
+/*[clinic end generated code: output=ba7a097ca230102b input=37ffb97d06ff4adb]*/
{
- Py_ssize_t n = 0;
PyObject *res = NULL;
CHECK_INITIALIZED(self)
CHECK_CLOSED(self, "peek of closed file")
- if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
- return NULL;
- }
-
if (!ENTER_BUFFERED(self))
return NULL;
@@ -911,16 +889,19 @@ end:
return res;
}
+/*[clinic input]
+_io._Buffered.read
+ size as n: io_ssize_t = -1
+ /
+[clinic start generated code]*/
+
static PyObject *
-buffered_read(buffered *self, PyObject *args)
+_io__Buffered_read_impl(buffered *self, Py_ssize_t n)
+/*[clinic end generated code: output=f41c78bb15b9bbe9 input=c0939ec7f9e9354f]*/
{
- Py_ssize_t n = -1;
PyObject *res;
CHECK_INITIALIZED(self)
- if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
- return NULL;
- }
if (n < -1) {
PyErr_SetString(PyExc_ValueError,
"read length must be positive or -1");
@@ -949,17 +930,20 @@ buffered_read(buffered *self, PyObject *args)
return res;
}
+/*[clinic input]
+_io._Buffered.read1
+ size as n: Py_ssize_t
+ /
+[clinic start generated code]*/
+
static PyObject *
-buffered_read1(buffered *self, PyObject *args)
+_io__Buffered_read1_impl(buffered *self, Py_ssize_t n)
+/*[clinic end generated code: output=bcc4fb4e54d103a3 input=8d2869c18b983184]*/
{
- Py_ssize_t n, have, r;
+ Py_ssize_t have, r;
PyObject *res = NULL;
CHECK_INITIALIZED(self)
- if (!PyArg_ParseTuple(args, "n:read1", &n)) {
- return NULL;
- }
-
if (n < 0) {
PyErr_SetString(PyExc_ValueError,
"read length must be positive");
@@ -1003,32 +987,27 @@ buffered_read1(buffered *self, PyObject *args)
}
static PyObject *
-buffered_readinto(buffered *self, PyObject *args)
+_buffered_readinto_generic(buffered *self, Py_buffer *buffer, char readinto1)
{
- Py_buffer buf;
Py_ssize_t n, written = 0, remaining;
PyObject *res = NULL;
CHECK_INITIALIZED(self)
- if (!PyArg_ParseTuple(args, "w*:readinto", &buf))
- return NULL;
-
n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
if (n > 0) {
- if (n >= buf.len) {
- memcpy(buf.buf, self->buffer + self->pos, buf.len);
- self->pos += buf.len;
- res = PyLong_FromSsize_t(buf.len);
- goto end_unlocked;
+ if (n >= buffer->len) {
+ memcpy(buffer->buf, self->buffer + self->pos, buffer->len);
+ self->pos += buffer->len;
+ return PyLong_FromSsize_t(buffer->len);
}
- memcpy(buf.buf, self->buffer + self->pos, n);
+ memcpy(buffer->buf, self->buffer + self->pos, n);
self->pos += n;
written = n;
}
if (!ENTER_BUFFERED(self))
- goto end_unlocked;
+ return NULL;
if (self->writable) {
res = buffered_flush_and_rewind_unlocked(self);
@@ -1040,26 +1019,32 @@ buffered_readinto(buffered *self, PyObject *args)
_bufferedreader_reset_buf(self);
self->pos = 0;
- for (remaining = buf.len - written;
+ for (remaining = buffer->len - written;
remaining > 0;
written += n, remaining -= n) {
/* If remaining bytes is larger than internal buffer size, copy
* directly into caller's buffer. */
if (remaining > self->buffer_size) {
- n = _bufferedreader_raw_read(self, (char *) buf.buf + written,
+ n = _bufferedreader_raw_read(self, (char *) buffer->buf + written,
remaining);
}
- else {
+
+ /* In readinto1 mode, we do not want to fill the internal
+ buffer if we already have some data to return */
+ else if (!(readinto1 && written)) {
n = _bufferedreader_fill_buffer(self);
if (n > 0) {
if (n > remaining)
n = remaining;
- memcpy((char *) buf.buf + written,
+ memcpy((char *) buffer->buf + written,
self->buffer + self->pos, n);
self->pos += n;
continue; /* short circuit */
}
}
+ else
+ n = 0;
+
if (n == 0 || (n == -2 && written > 0))
break;
if (n < 0) {
@@ -1069,16 +1054,47 @@ buffered_readinto(buffered *self, PyObject *args)
}
goto end;
}
+
+ /* At most one read in readinto1 mode */
+ if (readinto1) {
+ written += n;
+ break;
+ }
}
res = PyLong_FromSsize_t(written);
end:
LEAVE_BUFFERED(self);
-end_unlocked:
- PyBuffer_Release(&buf);
return res;
}
+/*[clinic input]
+_io._Buffered.readinto
+ buffer: Py_buffer(accept={rwbuffer})
+ /
+[clinic start generated code]*/
+
+static PyObject *
+_io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer)
+/*[clinic end generated code: output=bcb376580b1d8170 input=ed6b98b7a20a3008]*/
+{
+ return _buffered_readinto_generic(self, buffer, 0);
+}
+
+/*[clinic input]
+_io._Buffered.readinto1
+ buffer: Py_buffer(accept={rwbuffer})
+ /
+[clinic start generated code]*/
+
+static PyObject *
+_io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer)
+/*[clinic end generated code: output=6e5c6ac5868205d6 input=4455c5d55fdf1687]*/
+{
+ return _buffered_readinto_generic(self, buffer, 1);
+}
+
+
static PyObject *
_buffered_readline(buffered *self, Py_ssize_t limit)
{
@@ -1190,15 +1206,18 @@ end_unlocked:
return res;
}
+/*[clinic input]
+_io._Buffered.readline
+ size: io_ssize_t = -1
+ /
+[clinic start generated code]*/
+
static PyObject *
-buffered_readline(buffered *self, PyObject *args)
+_io__Buffered_readline_impl(buffered *self, Py_ssize_t size)
+/*[clinic end generated code: output=24dd2aa6e33be83c input=ff1e0df821cb4e5c]*/
{
- Py_ssize_t limit = -1;
-
CHECK_INITIALIZED(self)
- if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
- return NULL;
- return _buffered_readline(self, limit);
+ return _buffered_readline(self, size);
}
@@ -1216,17 +1235,21 @@ buffered_tell(buffered *self, PyObject *args)
return PyLong_FromOff_t(pos);
}
+/*[clinic input]
+_io._Buffered.seek
+ target as targetobj: object
+ whence: int = 0
+ /
+[clinic start generated code]*/
+
static PyObject *
-buffered_seek(buffered *self, PyObject *args)
+_io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
+/*[clinic end generated code: output=7ae0e8dc46efdefb input=a9c4920bfcba6163]*/
{
Py_off_t target, n;
- int whence = 0;
- PyObject *targetobj, *res = NULL;
+ PyObject *res = NULL;
CHECK_INITIALIZED(self)
- if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
- return NULL;
- }
/* Do some error checking instead of trusting OS 'seek()'
** error detection, just in case.
@@ -1308,17 +1331,19 @@ end:
return res;
}
+/*[clinic input]
+_io._Buffered.truncate
+ pos: object = None
+ /
+[clinic start generated code]*/
+
static PyObject *
-buffered_truncate(buffered *self, PyObject *args)
+_io__Buffered_truncate_impl(buffered *self, PyObject *pos)
+/*[clinic end generated code: output=667ca03c60c270de input=8a1be34d57cca2d3]*/
{
- PyObject *pos = Py_None;
PyObject *res = NULL;
CHECK_INITIALIZED(self)
- if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
- return NULL;
- }
-
if (!ENTER_BUFFERED(self))
return NULL;
@@ -1403,29 +1428,27 @@ buffered_repr(buffered *self)
* class BufferedReader
*/
-PyDoc_STRVAR(bufferedreader_doc,
- "Create a new buffered reader using the given readable raw IO object.");
-
static void _bufferedreader_reset_buf(buffered *self)
{
self->read_end = -1;
}
+/*[clinic input]
+_io.BufferedReader.__init__
+ raw: object
+ buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
+
+Create a new buffered reader using the given readable raw IO object.
+[clinic start generated code]*/
+
static int
-bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
+_io_BufferedReader___init___impl(buffered *self, PyObject *raw,
+ Py_ssize_t buffer_size)
+/*[clinic end generated code: output=cddcfefa0ed294c4 input=fb887e06f11b4e48]*/
{
- char *kwlist[] = {"raw", "buffer_size", NULL};
- Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
- PyObject *raw;
-
self->ok = 0;
self->detached = 0;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
- &raw, &buffer_size)) {
- return -1;
- }
-
if (_PyIOBase_check_readable(raw, Py_True) == NULL)
return -1;
@@ -1746,111 +1769,12 @@ _bufferedreader_peek_unlocked(buffered *self)
self->pos = 0;
return PyBytes_FromStringAndSize(self->buffer, r);
}
-
-static PyMethodDef bufferedreader_methods[] = {
- /* BufferedIOMixin methods */
- {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
- {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
- {"close", (PyCFunction)buffered_close, METH_NOARGS},
- {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
- {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
- {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
- {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
- {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
- {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
- {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
-
- {"read", (PyCFunction)buffered_read, METH_VARARGS},
- {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
- {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
- {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
- {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
- {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
- {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
- {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
- {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
- {NULL, NULL}
-};
-
-static PyMemberDef bufferedreader_members[] = {
- {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
- {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
- {NULL}
-};
-
-static PyGetSetDef bufferedreader_getset[] = {
- {"closed", (getter)buffered_closed_get, NULL, NULL},
- {"name", (getter)buffered_name_get, NULL, NULL},
- {"mode", (getter)buffered_mode_get, NULL, NULL},
- {NULL}
-};
-
-
-PyTypeObject PyBufferedReader_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io.BufferedReader", /*tp_name*/
- sizeof(buffered), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)buffered_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare */
- (reprfunc)buffered_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
- | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
- bufferedreader_doc, /* tp_doc */
- (traverseproc)buffered_traverse, /* tp_traverse */
- (inquiry)buffered_clear, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
- 0, /* tp_iter */
- (iternextfunc)buffered_iternext, /* tp_iternext */
- bufferedreader_methods, /* tp_methods */
- bufferedreader_members, /* tp_members */
- bufferedreader_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(buffered, dict), /* tp_dictoffset */
- (initproc)bufferedreader_init, /* tp_init */
- 0, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- 0, /* tp_del */
- 0, /* tp_version_tag */
- 0, /* tp_finalize */
-};
/*
* class BufferedWriter
*/
-PyDoc_STRVAR(bufferedwriter_doc,
- "A buffer for a writeable sequential RawIO object.\n"
- "\n"
- "The constructor creates a BufferedWriter for the given writeable raw\n"
- "stream. If the buffer_size is not given, it defaults to\n"
- "DEFAULT_BUFFER_SIZE.\n"
- );
-
static void
_bufferedwriter_reset_buf(buffered *self)
{
@@ -1858,21 +1782,26 @@ _bufferedwriter_reset_buf(buffered *self)
self->write_end = -1;
}
+/*[clinic input]
+_io.BufferedWriter.__init__
+ raw: object
+ buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
+
+A buffer for a writeable sequential RawIO object.
+
+The constructor creates a BufferedWriter for the given writeable raw
+stream. If the buffer_size is not given, it defaults to
+DEFAULT_BUFFER_SIZE.
+[clinic start generated code]*/
+
static int
-bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
+_io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
+ Py_ssize_t buffer_size)
+/*[clinic end generated code: output=c8942a020c0dee64 input=914be9b95e16007b]*/
{
- char *kwlist[] = {"raw", "buffer_size", NULL};
- Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
- PyObject *raw;
-
self->ok = 0;
self->detached = 0;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedWriter", kwlist,
- &raw, &buffer_size)) {
- return -1;
- }
-
if (_PyIOBase_check_writable(raw, Py_True) == NULL)
return -1;
@@ -1993,29 +1922,28 @@ error:
return NULL;
}
+/*[clinic input]
+_io.BufferedWriter.write
+ buffer: Py_buffer
+ /
+[clinic start generated code]*/
+
static PyObject *
-bufferedwriter_write(buffered *self, PyObject *args)
+_io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
+/*[clinic end generated code: output=7f8d1365759bfc6b input=dd87dd85fc7f8850]*/
{
PyObject *res = NULL;
- Py_buffer buf;
Py_ssize_t written, avail, remaining;
Py_off_t offset;
CHECK_INITIALIZED(self)
- if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
- return NULL;
- }
-
if (IS_CLOSED(self)) {
PyErr_SetString(PyExc_ValueError, "write to closed file");
- PyBuffer_Release(&buf);
return NULL;
}
- if (!ENTER_BUFFERED(self)) {
- PyBuffer_Release(&buf);
+ if (!ENTER_BUFFERED(self))
return NULL;
- }
/* Fast path: the data to write can be fully buffered. */
if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
@@ -2023,15 +1951,15 @@ bufferedwriter_write(buffered *self, PyObject *args)
self->raw_pos = 0;
}
avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
- if (buf.len <= avail) {
- memcpy(self->buffer + self->pos, buf.buf, buf.len);
+ if (buffer->len <= avail) {
+ memcpy(self->buffer + self->pos, buffer->buf, buffer->len);
if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
self->write_pos = self->pos;
}
- ADJUST_POSITION(self, self->pos + buf.len);
+ ADJUST_POSITION(self, self->pos + buffer->len);
if (self->pos > self->write_end)
self->write_end = self->pos;
- written = buf.len;
+ written = buffer->len;
goto end;
}
@@ -2054,17 +1982,17 @@ bufferedwriter_write(buffered *self, PyObject *args)
self->write_pos = 0;
avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
Py_off_t, Py_ssize_t);
- if (buf.len <= avail) {
+ if (buffer->len <= avail) {
/* Everything can be buffered */
PyErr_Clear();
- memcpy(self->buffer + self->write_end, buf.buf, buf.len);
- self->write_end += buf.len;
- self->pos += buf.len;
- written = buf.len;
+ memcpy(self->buffer + self->write_end, buffer->buf, buffer->len);
+ self->write_end += buffer->len;
+ self->pos += buffer->len;
+ written = buffer->len;
goto end;
}
/* Buffer as much as possible. */
- memcpy(self->buffer + self->write_end, buf.buf, avail);
+ memcpy(self->buffer + self->write_end, buffer->buf, avail);
self->write_end += avail;
self->pos += avail;
/* XXX Modifying the existing exception e using the pointer w
@@ -2090,11 +2018,11 @@ bufferedwriter_write(buffered *self, PyObject *args)
}
/* Then write buf itself. At this point the buffer has been emptied. */
- remaining = buf.len;
+ remaining = buffer->len;
written = 0;
while (remaining > self->buffer_size) {
Py_ssize_t n = _bufferedwriter_raw_write(
- self, (char *) buf.buf + written, buf.len - written);
+ self, (char *) buffer->buf + written, buffer->len - written);
if (n == -1) {
goto error;
} else if (n == -2) {
@@ -2102,7 +2030,7 @@ bufferedwriter_write(buffered *self, PyObject *args)
if (remaining > self->buffer_size) {
/* Can't buffer everything, still buffer as much as possible */
memcpy(self->buffer,
- (char *) buf.buf + written, self->buffer_size);
+ (char *) buffer->buf + written, self->buffer_size);
self->raw_pos = 0;
ADJUST_POSITION(self, self->buffer_size);
self->write_end = self->buffer_size;
@@ -2125,7 +2053,7 @@ bufferedwriter_write(buffered *self, PyObject *args)
if (self->readable)
_bufferedreader_reset_buf(self);
if (remaining > 0) {
- memcpy(self->buffer, (char *) buf.buf + written, remaining);
+ memcpy(self->buffer, (char *) buffer->buf + written, remaining);
written += remaining;
}
self->write_pos = 0;
@@ -2139,96 +2067,8 @@ end:
error:
LEAVE_BUFFERED(self)
- PyBuffer_Release(&buf);
return res;
}
-
-static PyMethodDef bufferedwriter_methods[] = {
- /* BufferedIOMixin methods */
- {"close", (PyCFunction)buffered_close, METH_NOARGS},
- {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
- {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
- {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
- {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
- {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
- {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
- {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
- {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
-
- {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
- {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
- {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
- {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
- {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
- {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
- {NULL, NULL}
-};
-
-static PyMemberDef bufferedwriter_members[] = {
- {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
- {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
- {NULL}
-};
-
-static PyGetSetDef bufferedwriter_getset[] = {
- {"closed", (getter)buffered_closed_get, NULL, NULL},
- {"name", (getter)buffered_name_get, NULL, NULL},
- {"mode", (getter)buffered_mode_get, NULL, NULL},
- {NULL}
-};
-
-
-PyTypeObject PyBufferedWriter_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io.BufferedWriter", /*tp_name*/
- sizeof(buffered), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)buffered_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare */
- (reprfunc)buffered_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
- | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
- bufferedwriter_doc, /* tp_doc */
- (traverseproc)buffered_traverse, /* tp_traverse */
- (inquiry)buffered_clear, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
- 0, /* tp_iter */
- 0, /* tp_iternext */
- bufferedwriter_methods, /* tp_methods */
- bufferedwriter_members, /* tp_members */
- bufferedwriter_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(buffered, dict), /* tp_dictoffset */
- (initproc)bufferedwriter_init, /* tp_init */
- 0, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- 0, /* tp_del */
- 0, /* tp_version_tag */
- 0, /* tp_finalize */
-};
@@ -2236,18 +2076,6 @@ PyTypeObject PyBufferedWriter_Type = {
* BufferedRWPair
*/
-PyDoc_STRVAR(bufferedrwpair_doc,
- "A buffered reader and writer object together.\n"
- "\n"
- "A buffered reader object and buffered writer object put together to\n"
- "form a sequential IO object that can read and write. This is typically\n"
- "used with a socket or two-way pipe.\n"
- "\n"
- "reader and writer are RawIOBase objects that are readable and\n"
- "writeable respectively. If the buffer_size is omitted it defaults to\n"
- "DEFAULT_BUFFER_SIZE.\n"
- );
-
/* XXX The usefulness of this (compared to having two separate IO objects) is
* questionable.
*/
@@ -2260,17 +2088,29 @@ typedef struct {
PyObject *weakreflist;
} rwpair;
-static int
-bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
-{
- PyObject *reader, *writer;
- Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
+/*[clinic input]
+_io.BufferedRWPair.__init__
+ reader: object
+ writer: object
+ buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
+ /
- if (!PyArg_ParseTuple(args, "OO|n:BufferedRWPair", &reader, &writer,
- &buffer_size)) {
- return -1;
- }
+A buffered reader and writer object together.
+
+A buffered reader object and buffered writer object put together to
+form a sequential IO object that can read and write. This is typically
+used with a socket or two-way pipe.
+reader and writer are RawIOBase objects that are readable and
+writeable respectively. If the buffer_size is omitted it defaults to
+DEFAULT_BUFFER_SIZE.
+[clinic start generated code]*/
+
+static int
+_io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader,
+ PyObject *writer, Py_ssize_t buffer_size)
+/*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/
+{
if (_PyIOBase_check_readable(reader, Py_True) == NULL)
return -1;
if (_PyIOBase_check_writable(writer, Py_True) == NULL)
@@ -2365,6 +2205,12 @@ bufferedrwpair_readinto(rwpair *self, PyObject *args)
}
static PyObject *
+bufferedrwpair_readinto1(rwpair *self, PyObject *args)
+{
+ return _forward_call(self->reader, &PyId_readinto1, args);
+}
+
+static PyObject *
bufferedrwpair_write(rwpair *self, PyObject *args)
{
return _forward_call(self->writer, &PyId_write, args);
@@ -2429,12 +2275,313 @@ bufferedrwpair_closed_get(rwpair *self, void *context)
}
return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
}
+
+
+
+/*
+ * BufferedRandom
+ */
+
+/*[clinic input]
+_io.BufferedRandom.__init__
+ raw: object
+ buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
+
+A buffered interface to random access streams.
+
+The constructor creates a reader and writer for a seekable stream,
+raw, given in the first argument. If the buffer_size is omitted it
+defaults to DEFAULT_BUFFER_SIZE.
+[clinic start generated code]*/
+
+static int
+_io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
+ Py_ssize_t buffer_size)
+/*[clinic end generated code: output=d3d64eb0f64e64a3 input=a4e818fb86d0e50c]*/
+{
+ self->ok = 0;
+ self->detached = 0;
+
+ if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
+ return -1;
+ if (_PyIOBase_check_readable(raw, Py_True) == NULL)
+ return -1;
+ if (_PyIOBase_check_writable(raw, Py_True) == NULL)
+ return -1;
+
+ Py_CLEAR(self->raw);
+ Py_INCREF(raw);
+ self->raw = raw;
+ self->buffer_size = buffer_size;
+ self->readable = 1;
+ self->writable = 1;
+
+ if (_buffered_init(self) < 0)
+ return -1;
+ _bufferedreader_reset_buf(self);
+ _bufferedwriter_reset_buf(self);
+ self->pos = 0;
+
+ self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
+ Py_TYPE(raw) == &PyFileIO_Type);
+
+ self->ok = 1;
+ return 0;
+}
+
+#include "clinic/bufferedio.c.h"
+
+
+static PyMethodDef bufferediobase_methods[] = {
+ _IO__BUFFEREDIOBASE_DETACH_METHODDEF
+ {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
+ {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
+ _IO__BUFFEREDIOBASE_READINTO_METHODDEF
+ _IO__BUFFEREDIOBASE_READINTO1_METHODDEF
+ {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
+ {NULL, NULL}
+};
+
+PyTypeObject PyBufferedIOBase_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "_io._BufferedIOBase", /*tp_name*/
+ 0, /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare */
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
+ | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
+ bufferediobase_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ bufferediobase_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyIOBase_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0, /* tp_del */
+ 0, /* tp_version_tag */
+ 0, /* tp_finalize */
+};
+
+
+static PyMethodDef bufferedreader_methods[] = {
+ /* BufferedIOMixin methods */
+ {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
+ {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
+ {"close", (PyCFunction)buffered_close, METH_NOARGS},
+ {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
+ {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
+ {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
+ {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
+ {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
+ {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
+ {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
+
+ _IO__BUFFERED_READ_METHODDEF
+ _IO__BUFFERED_PEEK_METHODDEF
+ _IO__BUFFERED_READ1_METHODDEF
+ _IO__BUFFERED_READINTO_METHODDEF
+ _IO__BUFFERED_READINTO1_METHODDEF
+ _IO__BUFFERED_READLINE_METHODDEF
+ _IO__BUFFERED_SEEK_METHODDEF
+ {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
+ _IO__BUFFERED_TRUNCATE_METHODDEF
+ {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
+ {NULL, NULL}
+};
+
+static PyMemberDef bufferedreader_members[] = {
+ {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
+ {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
+ {NULL}
+};
+
+static PyGetSetDef bufferedreader_getset[] = {
+ {"closed", (getter)buffered_closed_get, NULL, NULL},
+ {"name", (getter)buffered_name_get, NULL, NULL},
+ {"mode", (getter)buffered_mode_get, NULL, NULL},
+ {NULL}
+};
+
+
+PyTypeObject PyBufferedReader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "_io.BufferedReader", /*tp_name*/
+ sizeof(buffered), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)buffered_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare */
+ (reprfunc)buffered_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
+ | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
+ _io_BufferedReader___init____doc__, /* tp_doc */
+ (traverseproc)buffered_traverse, /* tp_traverse */
+ (inquiry)buffered_clear, /* tp_clear */
+ 0, /* tp_richcompare */
+ offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
+ 0, /* tp_iter */
+ (iternextfunc)buffered_iternext, /* tp_iternext */
+ bufferedreader_methods, /* tp_methods */
+ bufferedreader_members, /* tp_members */
+ bufferedreader_getset, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ offsetof(buffered, dict), /* tp_dictoffset */
+ _io_BufferedReader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0, /* tp_del */
+ 0, /* tp_version_tag */
+ 0, /* tp_finalize */
+};
+
+
+static PyMethodDef bufferedwriter_methods[] = {
+ /* BufferedIOMixin methods */
+ {"close", (PyCFunction)buffered_close, METH_NOARGS},
+ {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
+ {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
+ {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
+ {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
+ {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
+ {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
+ {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
+ {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
+
+ _IO_BUFFEREDWRITER_WRITE_METHODDEF
+ _IO__BUFFERED_TRUNCATE_METHODDEF
+ {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
+ _IO__BUFFERED_SEEK_METHODDEF
+ {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
+ {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
+ {NULL, NULL}
+};
+
+static PyMemberDef bufferedwriter_members[] = {
+ {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
+ {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
+ {NULL}
+};
+
+static PyGetSetDef bufferedwriter_getset[] = {
+ {"closed", (getter)buffered_closed_get, NULL, NULL},
+ {"name", (getter)buffered_name_get, NULL, NULL},
+ {"mode", (getter)buffered_mode_get, NULL, NULL},
+ {NULL}
+};
+
+
+PyTypeObject PyBufferedWriter_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "_io.BufferedWriter", /*tp_name*/
+ sizeof(buffered), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)buffered_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare */
+ (reprfunc)buffered_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
+ | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
+ _io_BufferedWriter___init____doc__, /* tp_doc */
+ (traverseproc)buffered_traverse, /* tp_traverse */
+ (inquiry)buffered_clear, /* tp_clear */
+ 0, /* tp_richcompare */
+ offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ bufferedwriter_methods, /* tp_methods */
+ bufferedwriter_members, /* tp_members */
+ bufferedwriter_getset, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ offsetof(buffered, dict), /* tp_dictoffset */
+ _io_BufferedWriter___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0, /* tp_del */
+ 0, /* tp_version_tag */
+ 0, /* tp_finalize */
+};
+
static PyMethodDef bufferedrwpair_methods[] = {
{"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
{"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
{"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
{"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
+ {"readinto1", (PyCFunction)bufferedrwpair_readinto1, METH_VARARGS},
{"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
{"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
@@ -2477,7 +2624,7 @@ PyTypeObject PyBufferedRWPair_Type = {
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
- bufferedrwpair_doc, /* tp_doc */
+ _io_BufferedRWPair___init____doc__, /* tp_doc */
(traverseproc)bufferedrwpair_traverse, /* tp_traverse */
(inquiry)bufferedrwpair_clear, /* tp_clear */
0, /* tp_richcompare */
@@ -2492,7 +2639,7 @@ PyTypeObject PyBufferedRWPair_Type = {
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(rwpair, dict), /* tp_dictoffset */
- (initproc)bufferedrwpair_init, /* tp_init */
+ _io_BufferedRWPair___init__, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
0, /* tp_free */
@@ -2506,62 +2653,7 @@ PyTypeObject PyBufferedRWPair_Type = {
0, /* tp_version_tag */
0, /* tp_finalize */
};
-
-
-/*
- * BufferedRandom
- */
-
-PyDoc_STRVAR(bufferedrandom_doc,
- "A buffered interface to random access streams.\n"
- "\n"
- "The constructor creates a reader and writer for a seekable stream,\n"
- "raw, given in the first argument. If the buffer_size is omitted it\n"
- "defaults to DEFAULT_BUFFER_SIZE.\n"
- );
-
-static int
-bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
-{
- char *kwlist[] = {"raw", "buffer_size", NULL};
- Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
- PyObject *raw;
-
- self->ok = 0;
- self->detached = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedRandom", kwlist,
- &raw, &buffer_size)) {
- return -1;
- }
-
- if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
- return -1;
- if (_PyIOBase_check_readable(raw, Py_True) == NULL)
- return -1;
- if (_PyIOBase_check_writable(raw, Py_True) == NULL)
- return -1;
-
- Py_CLEAR(self->raw);
- Py_INCREF(raw);
- self->raw = raw;
- self->buffer_size = buffer_size;
- self->readable = 1;
- self->writable = 1;
-
- if (_buffered_init(self) < 0)
- return -1;
- _bufferedreader_reset_buf(self);
- _bufferedwriter_reset_buf(self);
- self->pos = 0;
-
- self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
- Py_TYPE(raw) == &PyFileIO_Type);
-
- self->ok = 1;
- return 0;
-}
static PyMethodDef bufferedrandom_methods[] = {
/* BufferedIOMixin methods */
@@ -2577,15 +2669,16 @@ static PyMethodDef bufferedrandom_methods[] = {
{"flush", (PyCFunction)buffered_flush, METH_NOARGS},
- {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
+ _IO__BUFFERED_SEEK_METHODDEF
{"tell", (PyCFunction)buffered_tell, METH_NOARGS},
- {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
- {"read", (PyCFunction)buffered_read, METH_VARARGS},
- {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
- {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
- {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
- {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
- {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
+ _IO__BUFFERED_TRUNCATE_METHODDEF
+ _IO__BUFFERED_READ_METHODDEF
+ _IO__BUFFERED_READ1_METHODDEF
+ _IO__BUFFERED_READINTO_METHODDEF
+ _IO__BUFFERED_READINTO1_METHODDEF
+ _IO__BUFFERED_READLINE_METHODDEF
+ _IO__BUFFERED_PEEK_METHODDEF
+ _IO_BUFFEREDWRITER_WRITE_METHODDEF
{"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
{NULL, NULL}
};
@@ -2626,7 +2719,7 @@ PyTypeObject PyBufferedRandom_Type = {
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
- bufferedrandom_doc, /* tp_doc */
+ _io_BufferedRandom___init____doc__, /* tp_doc */
(traverseproc)buffered_traverse, /* tp_traverse */
(inquiry)buffered_clear, /* tp_clear */
0, /* tp_richcompare */
@@ -2641,7 +2734,7 @@ PyTypeObject PyBufferedRandom_Type = {
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(buffered, dict), /*tp_dictoffset*/
- (initproc)bufferedrandom_init, /* tp_init */
+ _io_BufferedRandom___init__, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
0, /* tp_free */
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 4652356f31..31cc1f79a1 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -2,12 +2,17 @@
#include "structmember.h" /* for offsetof() */
#include "_iomodule.h"
+/*[clinic input]
+module _io
+class _io.BytesIO "bytesio *" "&PyBytesIO_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7f50ec034f5c0b26]*/
+
typedef struct {
PyObject_HEAD
- char *buf;
+ PyObject *buf;
Py_ssize_t pos;
Py_ssize_t string_size;
- size_t buf_size;
PyObject *dict;
PyObject *weakreflist;
Py_ssize_t exports;
@@ -18,6 +23,12 @@ typedef struct {
bytesio *source;
} bytesiobuf;
+/* The bytesio object can be in three states:
+ * Py_REFCNT(buf) == 1, exports == 0.
+ * Py_REFCNT(buf) > 1. exports == 0,
+ first modification or export causes the internal buffer copying.
+ * exports > 0. Py_REFCNT(buf) == 1, any modifications are forbidden.
+*/
#define CHECK_CLOSED(self) \
if ((self)->buf == NULL) { \
@@ -33,40 +44,64 @@ typedef struct {
return NULL; \
}
+#define SHARED_BUF(self) (Py_REFCNT((self)->buf) > 1)
+
/* Internal routine to get a line from the buffer of a BytesIO
object. Returns the length between the current position to the
next newline character. */
static Py_ssize_t
-get_line(bytesio *self, char **output)
+scan_eol(bytesio *self, Py_ssize_t len)
{
- char *n;
- const char *str_end;
- Py_ssize_t len;
+ const char *start, *n;
+ Py_ssize_t maxlen;
assert(self->buf != NULL);
+ assert(self->pos >= 0);
- /* Move to the end of the line, up to the end of the string, s. */
- str_end = self->buf + self->string_size;
- for (n = self->buf + self->pos;
- n < str_end && *n != '\n';
- n++);
-
- /* Skip the newline character */
- if (n < str_end)
- n++;
-
- /* Get the length from the current position to the end of the line. */
- len = n - (self->buf + self->pos);
- *output = self->buf + self->pos;
+ if (self->pos >= self->string_size)
+ return 0;
+ /* Move to the end of the line, up to the end of the string, s. */
+ maxlen = self->string_size - self->pos;
+ if (len < 0 || len > maxlen)
+ len = maxlen;
+
+ if (len) {
+ start = PyBytes_AS_STRING(self->buf) + self->pos;
+ n = memchr(start, '\n', len);
+ if (n)
+ /* Get the length from the current position to the end of
+ the line. */
+ len = n - start + 1;
+ }
assert(len >= 0);
assert(self->pos < PY_SSIZE_T_MAX - len);
- self->pos += len;
return len;
}
+/* Internal routine for detaching the shared buffer of BytesIO objects.
+ The caller should ensure that the 'size' argument is non-negative and
+ not lesser than self->string_size. Returns 0 on success, -1 otherwise. */
+static int
+unshare_buffer(bytesio *self, size_t size)
+{
+ PyObject *new_buf, *old_buf;
+ assert(SHARED_BUF(self));
+ assert(self->exports == 0);
+ assert(size >= (size_t)self->string_size);
+ new_buf = PyBytes_FromStringAndSize(NULL, size);
+ if (new_buf == NULL)
+ return -1;
+ memcpy(PyBytes_AS_STRING(new_buf), PyBytes_AS_STRING(self->buf),
+ self->string_size);
+ old_buf = self->buf;
+ self->buf = new_buf;
+ Py_DECREF(old_buf);
+ return 0;
+}
+
/* Internal routine for changing the size of the buffer of BytesIO objects.
The caller should ensure that the 'size' argument is non-negative. Returns
0 on success, -1 otherwise. */
@@ -75,8 +110,7 @@ resize_buffer(bytesio *self, size_t size)
{
/* Here, unsigned types are used to avoid dealing with signed integer
overflow, which is undefined in C. */
- size_t alloc = self->buf_size;
- char *new_buf = NULL;
+ size_t alloc = PyBytes_GET_SIZE(self->buf);
assert(self->buf != NULL);
@@ -104,13 +138,15 @@ resize_buffer(bytesio *self, size_t size)
if (alloc > ((size_t)-1) / sizeof(char))
goto overflow;
- new_buf = (char *)PyMem_Realloc(self->buf, alloc * sizeof(char));
- if (new_buf == NULL) {
- PyErr_NoMemory();
- return -1;
+
+ if (SHARED_BUF(self)) {
+ if (unshare_buffer(self, alloc) < 0)
+ return -1;
+ }
+ else {
+ if (_PyBytes_Resize(&self->buf, alloc) < 0)
+ return -1;
}
- self->buf_size = alloc;
- self->buf = new_buf;
return 0;
@@ -125,12 +161,18 @@ resize_buffer(bytesio *self, size_t size)
static Py_ssize_t
write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
{
+ size_t endpos;
assert(self->buf != NULL);
assert(self->pos >= 0);
assert(len >= 0);
- if ((size_t)self->pos + len > self->buf_size) {
- if (resize_buffer(self, (size_t)self->pos + len) < 0)
+ endpos = (size_t)self->pos + len;
+ if (endpos > (size_t)PyBytes_GET_SIZE(self->buf)) {
+ if (resize_buffer(self, endpos) < 0)
+ return -1;
+ }
+ else if (SHARED_BUF(self)) {
+ if (unshare_buffer(self, Py_MAX(endpos, (size_t)self->string_size)) < 0)
return -1;
}
@@ -143,18 +185,18 @@ write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
| | <--to pad-->|<---to write---> |
0 buf position
*/
- memset(self->buf + self->string_size, '\0',
+ memset(PyBytes_AS_STRING(self->buf) + self->string_size, '\0',
(self->pos - self->string_size) * sizeof(char));
}
/* Copy the data to the internal buffer, overwriting some of the existing
data if self->pos < self->string_size. */
- memcpy(self->buf + self->pos, bytes, len);
- self->pos += len;
+ memcpy(PyBytes_AS_STRING(self->buf) + self->pos, bytes, len);
+ self->pos = endpos;
/* Set the new length of the internal string if it has changed. */
- if (self->string_size < self->pos) {
- self->string_size = self->pos;
+ if ((size_t)self->string_size < endpos) {
+ self->string_size = endpos;
}
return len;
@@ -171,40 +213,71 @@ bytesio_get_closed(bytesio *self)
}
}
-PyDoc_STRVAR(readable_doc,
-"readable() -> bool. Returns True if the IO object can be read.");
+/*[clinic input]
+_io.BytesIO.readable
+
+Returns True if the IO object can be read.
+[clinic start generated code]*/
+
+static PyObject *
+_io_BytesIO_readable_impl(bytesio *self)
+/*[clinic end generated code: output=4e93822ad5b62263 input=96c5d0cccfb29f5c]*/
+{
+ CHECK_CLOSED(self);
+ Py_RETURN_TRUE;
+}
-PyDoc_STRVAR(writable_doc,
-"writable() -> bool. Returns True if the IO object can be written.");
+/*[clinic input]
+_io.BytesIO.writable
-PyDoc_STRVAR(seekable_doc,
-"seekable() -> bool. Returns True if the IO object can be seeked.");
+Returns True if the IO object can be written.
+[clinic start generated code]*/
-/* Generic getter for the writable, readable and seekable properties */
static PyObject *
-return_not_closed(bytesio *self)
+_io_BytesIO_writable_impl(bytesio *self)
+/*[clinic end generated code: output=64ff6a254b1150b8 input=700eed808277560a]*/
{
CHECK_CLOSED(self);
Py_RETURN_TRUE;
}
-PyDoc_STRVAR(flush_doc,
-"flush() -> None. Does nothing.");
+/*[clinic input]
+_io.BytesIO.seekable
+
+Returns True if the IO object can be seeked.
+[clinic start generated code]*/
+
+static PyObject *
+_io_BytesIO_seekable_impl(bytesio *self)
+/*[clinic end generated code: output=6b417f46dcc09b56 input=9421f65627a344dd]*/
+{
+ CHECK_CLOSED(self);
+ Py_RETURN_TRUE;
+}
+
+/*[clinic input]
+_io.BytesIO.flush
+
+Does nothing.
+[clinic start generated code]*/
static PyObject *
-bytesio_flush(bytesio *self)
+_io_BytesIO_flush_impl(bytesio *self)
+/*[clinic end generated code: output=187e3d781ca134a0 input=561ea490be4581a7]*/
{
CHECK_CLOSED(self);
Py_RETURN_NONE;
}
-PyDoc_STRVAR(getbuffer_doc,
-"getbuffer() -> bytes.\n"
-"\n"
-"Get a read-write view over the contents of the BytesIO object.");
+/*[clinic input]
+_io.BytesIO.getbuffer
+
+Get a read-write view over the contents of the BytesIO object.
+[clinic start generated code]*/
static PyObject *
-bytesio_getbuffer(bytesio *self)
+_io_BytesIO_getbuffer_impl(bytesio *self)
+/*[clinic end generated code: output=72cd7c6e13aa09ed input=8f738ef615865176]*/
{
PyTypeObject *type = &_PyBytesIOBuffer_Type;
bytesiobuf *buf;
@@ -222,59 +295,104 @@ bytesio_getbuffer(bytesio *self)
return view;
}
-PyDoc_STRVAR(getval_doc,
-"getvalue() -> bytes.\n"
-"\n"
-"Retrieve the entire contents of the BytesIO object.");
+/*[clinic input]
+_io.BytesIO.getvalue
+
+Retrieve the entire contents of the BytesIO object.
+[clinic start generated code]*/
static PyObject *
-bytesio_getvalue(bytesio *self)
+_io_BytesIO_getvalue_impl(bytesio *self)
+/*[clinic end generated code: output=b3f6a3233c8fd628 input=4b403ac0af3973ed]*/
{
CHECK_CLOSED(self);
- return PyBytes_FromStringAndSize(self->buf, self->string_size);
+ if (self->string_size <= 1 || self->exports > 0)
+ return PyBytes_FromStringAndSize(PyBytes_AS_STRING(self->buf),
+ self->string_size);
+
+ if (self->string_size != PyBytes_GET_SIZE(self->buf)) {
+ if (SHARED_BUF(self)) {
+ if (unshare_buffer(self, self->string_size) < 0)
+ return NULL;
+ }
+ else {
+ if (_PyBytes_Resize(&self->buf, self->string_size) < 0)
+ return NULL;
+ }
+ }
+ Py_INCREF(self->buf);
+ return self->buf;
}
-PyDoc_STRVAR(isatty_doc,
-"isatty() -> False.\n"
-"\n"
-"Always returns False since BytesIO objects are not connected\n"
-"to a tty-like device.");
+/*[clinic input]
+_io.BytesIO.isatty
+
+Always returns False.
+
+BytesIO objects are not connected to a TTY-like device.
+[clinic start generated code]*/
static PyObject *
-bytesio_isatty(bytesio *self)
+_io_BytesIO_isatty_impl(bytesio *self)
+/*[clinic end generated code: output=df67712e669f6c8f input=6f97f0985d13f827]*/
{
CHECK_CLOSED(self);
Py_RETURN_FALSE;
}
-PyDoc_STRVAR(tell_doc,
-"tell() -> current file position, an integer\n");
+/*[clinic input]
+_io.BytesIO.tell
+
+Current file position, an integer.
+[clinic start generated code]*/
static PyObject *
-bytesio_tell(bytesio *self)
+_io_BytesIO_tell_impl(bytesio *self)
+/*[clinic end generated code: output=b54b0f93cd0e5e1d input=b106adf099cb3657]*/
{
CHECK_CLOSED(self);
return PyLong_FromSsize_t(self->pos);
}
-PyDoc_STRVAR(read_doc,
-"read([size]) -> read at most size bytes, returned as a bytes object.\n"
-"\n"
-"If the size argument is negative, read until EOF is reached.\n"
-"Return an empty bytes object at EOF.");
+static PyObject *
+read_bytes(bytesio *self, Py_ssize_t size)
+{
+ char *output;
+
+ assert(self->buf != NULL);
+ assert(size <= self->string_size);
+ if (size > 1 &&
+ self->pos == 0 && size == PyBytes_GET_SIZE(self->buf) &&
+ self->exports == 0) {
+ self->pos += size;
+ Py_INCREF(self->buf);
+ return self->buf;
+ }
+
+ output = PyBytes_AS_STRING(self->buf) + self->pos;
+ self->pos += size;
+ return PyBytes_FromStringAndSize(output, size);
+}
+
+/*[clinic input]
+_io.BytesIO.read
+ size as arg: object = None
+ /
+
+Read at most size bytes, returned as a bytes object.
+
+If the size argument is negative, read until EOF is reached.
+Return an empty bytes object at EOF.
+[clinic start generated code]*/
static PyObject *
-bytesio_read(bytesio *self, PyObject *args)
+_io_BytesIO_read_impl(bytesio *self, PyObject *arg)
+/*[clinic end generated code: output=85dacb535c1e1781 input=cc7ba4a797bb1555]*/
{
Py_ssize_t size, n;
- char *output;
- PyObject *arg = Py_None;
CHECK_CLOSED(self);
- if (!PyArg_ParseTuple(args, "|O:read", &arg))
- return NULL;
-
if (PyLong_Check(arg)) {
size = PyLong_AsSsize_t(arg);
if (size == -1 && PyErr_Occurred())
@@ -298,52 +416,48 @@ bytesio_read(bytesio *self, PyObject *args)
size = 0;
}
- assert(self->buf != NULL);
- output = self->buf + self->pos;
- self->pos += size;
-
- return PyBytes_FromStringAndSize(output, size);
+ return read_bytes(self, size);
}
-PyDoc_STRVAR(read1_doc,
-"read1(size) -> read at most size bytes, returned as a bytes object.\n"
-"\n"
-"If the size argument is negative or omitted, read until EOF is reached.\n"
-"Return an empty bytes object at EOF.");
+/*[clinic input]
+_io.BytesIO.read1
+ size: object
+ /
+
+Read at most size bytes, returned as a bytes object.
+
+If the size argument is negative or omitted, read until EOF is reached.
+Return an empty bytes object at EOF.
+[clinic start generated code]*/
static PyObject *
-bytesio_read1(bytesio *self, PyObject *n)
+_io_BytesIO_read1(bytesio *self, PyObject *size)
+/*[clinic end generated code: output=16021f5d0ac3d4e2 input=d4f40bb8f2f99418]*/
{
- PyObject *arg, *res;
-
- arg = PyTuple_Pack(1, n);
- if (arg == NULL)
- return NULL;
- res = bytesio_read(self, arg);
- Py_DECREF(arg);
- return res;
+ return _io_BytesIO_read_impl(self, size);
}
-PyDoc_STRVAR(readline_doc,
-"readline([size]) -> next line from the file, as a bytes object.\n"
-"\n"
-"Retain newline. A non-negative size argument limits the maximum\n"
-"number of bytes to return (an incomplete line may be returned then).\n"
-"Return an empty bytes object at EOF.\n");
+/*[clinic input]
+_io.BytesIO.readline
+ size as arg: object = None
+ /
+
+Next line from the file, as a bytes object.
+
+Retain newline. A non-negative size argument limits the maximum
+number of bytes to return (an incomplete line may be returned then).
+Return an empty bytes object at EOF.
+[clinic start generated code]*/
static PyObject *
-bytesio_readline(bytesio *self, PyObject *args)
+_io_BytesIO_readline_impl(bytesio *self, PyObject *arg)
+/*[clinic end generated code: output=1c2115534a4f9276 input=ca31f06de6eab257]*/
{
Py_ssize_t size, n;
- char *output;
- PyObject *arg = Py_None;
CHECK_CLOSED(self);
- if (!PyArg_ParseTuple(args, "|O:readline", &arg))
- return NULL;
-
if (PyLong_Check(arg)) {
size = PyLong_AsSsize_t(arg);
if (size == -1 && PyErr_Occurred())
@@ -359,37 +473,33 @@ bytesio_readline(bytesio *self, PyObject *args)
return NULL;
}
- n = get_line(self, &output);
+ n = scan_eol(self, size);
- if (size >= 0 && size < n) {
- size = n - size;
- n -= size;
- self->pos -= size;
- }
-
- return PyBytes_FromStringAndSize(output, n);
+ return read_bytes(self, n);
}
-PyDoc_STRVAR(readlines_doc,
-"readlines([size]) -> list of strings, each a line from the file.\n"
-"\n"
-"Call readline() repeatedly and return a list of the lines so read.\n"
-"The optional size argument, if given, is an approximate bound on the\n"
-"total number of bytes in the lines returned.\n");
+/*[clinic input]
+_io.BytesIO.readlines
+ size as arg: object = None
+ /
+
+List of bytes objects, each a line from the file.
+
+Call readline() repeatedly and return a list of the lines so read.
+The optional size argument, if given, is an approximate bound on the
+total number of bytes in the lines returned.
+[clinic start generated code]*/
static PyObject *
-bytesio_readlines(bytesio *self, PyObject *args)
+_io_BytesIO_readlines_impl(bytesio *self, PyObject *arg)
+/*[clinic end generated code: output=09b8e34c880808ff input=691aa1314f2c2a87]*/
{
Py_ssize_t maxsize, size, n;
PyObject *result, *line;
char *output;
- PyObject *arg = Py_None;
CHECK_CLOSED(self);
- if (!PyArg_ParseTuple(args, "|O:readlines", &arg))
- return NULL;
-
if (PyLong_Check(arg)) {
maxsize = PyLong_AsSsize_t(arg);
if (maxsize == -1 && PyErr_Occurred())
@@ -410,7 +520,9 @@ bytesio_readlines(bytesio *self, PyObject *args)
if (!result)
return NULL;
- while ((n = get_line(self, &output)) != 0) {
+ output = PyBytes_AS_STRING(self->buf) + self->pos;
+ while ((n = scan_eol(self, -1)) != 0) {
+ self->pos += n;
line = PyBytes_FromStringAndSize(output, n);
if (!line)
goto on_error;
@@ -422,6 +534,7 @@ bytesio_readlines(bytesio *self, PyObject *args)
size += n;
if (maxsize > 0 && size >= maxsize)
break;
+ output += n;
}
return result;
@@ -430,25 +543,27 @@ bytesio_readlines(bytesio *self, PyObject *args)
return NULL;
}
-PyDoc_STRVAR(readinto_doc,
-"readinto(bytearray) -> int. Read up to len(b) bytes into b.\n"
-"\n"
-"Returns number of bytes read (0 for EOF), or None if the object\n"
-"is set not to block as has no data to read.");
+/*[clinic input]
+_io.BytesIO.readinto
+ buffer: Py_buffer(accept={rwbuffer})
+ /
+
+Read up to len(buffer) bytes into buffer.
+
+Returns number of bytes read (0 for EOF), or None if the object
+is set not to block as has no data to read.
+[clinic start generated code]*/
static PyObject *
-bytesio_readinto(bytesio *self, PyObject *arg)
+_io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer)
+/*[clinic end generated code: output=a5d407217dcf0639 input=71581f32635c3a31]*/
{
- Py_buffer buffer;
Py_ssize_t len, n;
CHECK_CLOSED(self);
- if (!PyArg_Parse(arg, "w*", &buffer))
- return NULL;
-
/* adjust invalid sizes */
- len = buffer.len;
+ len = buffer->len;
n = self->string_size - self->pos;
if (len > n) {
len = n;
@@ -456,33 +571,34 @@ bytesio_readinto(bytesio *self, PyObject *arg)
len = 0;
}
- memcpy(buffer.buf, self->buf + self->pos, len);
+ memcpy(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len);
assert(self->pos + len < PY_SSIZE_T_MAX);
assert(len >= 0);
self->pos += len;
- PyBuffer_Release(&buffer);
return PyLong_FromSsize_t(len);
}
-PyDoc_STRVAR(truncate_doc,
-"truncate([size]) -> int. Truncate the file to at most size bytes.\n"
-"\n"
-"Size defaults to the current file position, as returned by tell().\n"
-"The current file position is unchanged. Returns the new size.\n");
+/*[clinic input]
+_io.BytesIO.truncate
+ size as arg: object = None
+ /
+
+Truncate the file to at most size bytes.
+
+Size defaults to the current file position, as returned by tell().
+The current file position is unchanged. Returns the new size.
+[clinic start generated code]*/
static PyObject *
-bytesio_truncate(bytesio *self, PyObject *args)
+_io_BytesIO_truncate_impl(bytesio *self, PyObject *arg)
+/*[clinic end generated code: output=81e6be60e67ddd66 input=11ed1966835462ba]*/
{
Py_ssize_t size;
- PyObject *arg = Py_None;
CHECK_CLOSED(self);
CHECK_EXPORTS(self);
- if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
- return NULL;
-
if (PyLong_Check(arg)) {
size = PyLong_AsSsize_t(arg);
if (size == -1 && PyErr_Occurred())
@@ -516,49 +632,49 @@ bytesio_truncate(bytesio *self, PyObject *args)
static PyObject *
bytesio_iternext(bytesio *self)
{
- char *next;
Py_ssize_t n;
CHECK_CLOSED(self);
- n = get_line(self, &next);
+ n = scan_eol(self, -1);
- if (!next || n == 0)
+ if (n == 0)
return NULL;
- return PyBytes_FromStringAndSize(next, n);
+ return read_bytes(self, n);
}
-PyDoc_STRVAR(seek_doc,
-"seek(pos, whence=0) -> int. Change stream position.\n"
-"\n"
-"Seek to byte offset pos relative to position indicated by whence:\n"
-" 0 Start of stream (the default). pos should be >= 0;\n"
-" 1 Current position - pos may be negative;\n"
-" 2 End of stream - pos usually negative.\n"
-"Returns the new absolute position.");
+/*[clinic input]
+_io.BytesIO.seek
+ pos: Py_ssize_t
+ whence: int = 0
+ /
+
+Change stream position.
+
+Seek to byte offset pos relative to position indicated by whence:
+ 0 Start of stream (the default). pos should be >= 0;
+ 1 Current position - pos may be negative;
+ 2 End of stream - pos usually negative.
+Returns the new absolute position.
+[clinic start generated code]*/
static PyObject *
-bytesio_seek(bytesio *self, PyObject *args)
+_io_BytesIO_seek_impl(bytesio *self, Py_ssize_t pos, int whence)
+/*[clinic end generated code: output=c26204a68e9190e4 input=1e875e6ebc652948]*/
{
- Py_ssize_t pos;
- int mode = 0;
-
CHECK_CLOSED(self);
- if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode))
- return NULL;
-
- if (pos < 0 && mode == 0) {
+ if (pos < 0 && whence == 0) {
PyErr_Format(PyExc_ValueError,
"negative seek value %zd", pos);
return NULL;
}
- /* mode 0: offset relative to beginning of the string.
- mode 1: offset relative to current position.
- mode 2: offset relative the end of the string. */
- if (mode == 1) {
+ /* whence = 0: offset relative to beginning of the string.
+ whence = 1: offset relative to current position.
+ whence = 2: offset relative the end of the string. */
+ if (whence == 1) {
if (pos > PY_SSIZE_T_MAX - self->pos) {
PyErr_SetString(PyExc_OverflowError,
"new position too large");
@@ -566,7 +682,7 @@ bytesio_seek(bytesio *self, PyObject *args)
}
pos += self->pos;
}
- else if (mode == 2) {
+ else if (whence == 2) {
if (pos > PY_SSIZE_T_MAX - self->string_size) {
PyErr_SetString(PyExc_OverflowError,
"new position too large");
@@ -574,9 +690,9 @@ bytesio_seek(bytesio *self, PyObject *args)
}
pos += self->string_size;
}
- else if (mode != 0) {
+ else if (whence != 0) {
PyErr_Format(PyExc_ValueError,
- "invalid whence (%i, should be 0, 1 or 2)", mode);
+ "invalid whence (%i, should be 0, 1 or 2)", whence);
return NULL;
}
@@ -587,54 +703,63 @@ bytesio_seek(bytesio *self, PyObject *args)
return PyLong_FromSsize_t(self->pos);
}
-PyDoc_STRVAR(write_doc,
-"write(bytes) -> int. Write bytes to file.\n"
-"\n"
-"Return the number of bytes written.");
+/*[clinic input]
+_io.BytesIO.write
+ b: object
+ /
+
+Write bytes to file.
+
+Return the number of bytes written.
+[clinic start generated code]*/
static PyObject *
-bytesio_write(bytesio *self, PyObject *obj)
+_io_BytesIO_write(bytesio *self, PyObject *b)
+/*[clinic end generated code: output=53316d99800a0b95 input=f5ec7c8c64ed720a]*/
{
Py_ssize_t n = 0;
Py_buffer buf;
- PyObject *result = NULL;
CHECK_CLOSED(self);
CHECK_EXPORTS(self);
- if (PyObject_GetBuffer(obj, &buf, PyBUF_CONTIG_RO) < 0)
+ if (PyObject_GetBuffer(b, &buf, PyBUF_CONTIG_RO) < 0)
return NULL;
if (buf.len != 0)
n = write_bytes(self, buf.buf, buf.len);
- if (n >= 0)
- result = PyLong_FromSsize_t(n);
PyBuffer_Release(&buf);
- return result;
+ return n >= 0 ? PyLong_FromSsize_t(n) : NULL;
}
-PyDoc_STRVAR(writelines_doc,
-"writelines(lines) -> None. Write bytes objects to the file.\n"
-"\n"
-"Note that newlines are not added. The argument can be any iterable\n"
-"object producing bytes objects. This is equivalent to calling write() for\n"
-"each bytes object.");
+/*[clinic input]
+_io.BytesIO.writelines
+ lines: object
+ /
+
+Write lines to the file.
+
+Note that newlines are not added. lines can be any iterable object
+producing bytes-like objects. This is equivalent to calling write() for
+each element.
+[clinic start generated code]*/
static PyObject *
-bytesio_writelines(bytesio *self, PyObject *v)
+_io_BytesIO_writelines(bytesio *self, PyObject *lines)
+/*[clinic end generated code: output=7f33aa3271c91752 input=e972539176fc8fc1]*/
{
PyObject *it, *item;
PyObject *ret;
CHECK_CLOSED(self);
- it = PyObject_GetIter(v);
+ it = PyObject_GetIter(lines);
if (it == NULL)
return NULL;
while ((item = PyIter_Next(it)) != NULL) {
- ret = bytesio_write(self, item);
+ ret = _io_BytesIO_write(self, item);
Py_DECREF(item);
if (ret == NULL) {
Py_DECREF(it);
@@ -651,17 +776,18 @@ bytesio_writelines(bytesio *self, PyObject *v)
Py_RETURN_NONE;
}
-PyDoc_STRVAR(close_doc,
-"close() -> None. Disable all I/O operations.");
+/*[clinic input]
+_io.BytesIO.close
+
+Disable all I/O operations.
+[clinic start generated code]*/
static PyObject *
-bytesio_close(bytesio *self)
+_io_BytesIO_close_impl(bytesio *self)
+/*[clinic end generated code: output=1471bb9411af84a0 input=37e1f55556e61f60]*/
{
CHECK_EXPORTS(self);
- if (self->buf != NULL) {
- PyMem_Free(self->buf);
- self->buf = NULL;
- }
+ Py_CLEAR(self->buf);
Py_RETURN_NONE;
}
@@ -683,7 +809,7 @@ bytesio_close(bytesio *self)
static PyObject *
bytesio_getstate(bytesio *self)
{
- PyObject *initvalue = bytesio_getvalue(self);
+ PyObject *initvalue = _io_BytesIO_getvalue_impl(self);
PyObject *dict;
PyObject *state;
@@ -733,7 +859,7 @@ bytesio_setstate(bytesio *self, PyObject *state)
/* Set the value of the internal buffer. If state[0] does not support the
buffer protocol, bytesio_write will raise the appropriate TypeError. */
- result = bytesio_write(self, PyTuple_GET_ITEM(state, 0));
+ result = _io_BytesIO_write(self, PyTuple_GET_ITEM(state, 0));
if (result == NULL)
return NULL;
Py_DECREF(result);
@@ -791,10 +917,7 @@ bytesio_dealloc(bytesio *self)
"deallocated BytesIO object has exported buffers");
PyErr_Print();
}
- if (self->buf != NULL) {
- PyMem_Free(self->buf);
- self->buf = NULL;
- }
+ Py_CLEAR(self->buf);
Py_CLEAR(self->dict);
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
@@ -814,7 +937,7 @@ bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
/* tp_alloc initializes all the fields to zero. So we don't have to
initialize them here. */
- self->buf = (char *)PyMem_Malloc(0);
+ self->buf = PyBytes_FromStringAndSize(NULL, 0);
if (self->buf == NULL) {
Py_DECREF(self);
return PyErr_NoMemory();
@@ -823,27 +946,41 @@ bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject *)self;
}
-static int
-bytesio_init(bytesio *self, PyObject *args, PyObject *kwds)
-{
- char *kwlist[] = {"initial_bytes", NULL};
- PyObject *initvalue = NULL;
+/*[clinic input]
+_io.BytesIO.__init__
+ initial_bytes as initvalue: object(c_default="NULL") = b''
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:BytesIO", kwlist,
- &initvalue))
- return -1;
+Buffered I/O implementation using an in-memory bytes buffer.
+[clinic start generated code]*/
+static int
+_io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
+/*[clinic end generated code: output=65c0c51e24c5b621 input=aac7f31b67bf0fb6]*/
+{
/* In case, __init__ is called multiple times. */
self->string_size = 0;
self->pos = 0;
+ if (self->exports > 0) {
+ PyErr_SetString(PyExc_BufferError,
+ "Existing exports of data: object cannot be re-sized");
+ return -1;
+ }
if (initvalue && initvalue != Py_None) {
- PyObject *res;
- res = bytesio_write(self, initvalue);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- self->pos = 0;
+ if (PyBytes_CheckExact(initvalue)) {
+ Py_INCREF(initvalue);
+ Py_XDECREF(self->buf);
+ self->buf = initvalue;
+ self->string_size = PyBytes_GET_SIZE(initvalue);
+ }
+ else {
+ PyObject *res;
+ res = _io_BytesIO_write(self, initvalue);
+ if (res == NULL)
+ return -1;
+ Py_DECREF(res);
+ self->pos = 0;
+ }
}
return 0;
@@ -855,8 +992,8 @@ bytesio_sizeof(bytesio *self, void *unused)
Py_ssize_t res;
res = sizeof(bytesio);
- if (self->buf)
- res += self->buf_size;
+ if (self->buf && !SHARED_BUF(self))
+ res += _PySys_GetSizeOf(self->buf);
return PyLong_FromSsize_t(res);
}
@@ -875,6 +1012,8 @@ bytesio_clear(bytesio *self)
}
+#include "clinic/bytesio.c.h"
+
static PyGetSetDef bytesio_getsetlist[] = {
{"closed", (getter)bytesio_get_closed, NULL,
"True if the file is closed."},
@@ -882,36 +1021,30 @@ static PyGetSetDef bytesio_getsetlist[] = {
};
static struct PyMethodDef bytesio_methods[] = {
- {"readable", (PyCFunction)return_not_closed, METH_NOARGS, readable_doc},
- {"seekable", (PyCFunction)return_not_closed, METH_NOARGS, seekable_doc},
- {"writable", (PyCFunction)return_not_closed, METH_NOARGS, writable_doc},
- {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc},
- {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc},
- {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc},
- {"tell", (PyCFunction)bytesio_tell, METH_NOARGS, tell_doc},
- {"write", (PyCFunction)bytesio_write, METH_O, write_doc},
- {"writelines", (PyCFunction)bytesio_writelines, METH_O, writelines_doc},
- {"read1", (PyCFunction)bytesio_read1, METH_O, read1_doc},
- {"readinto", (PyCFunction)bytesio_readinto, METH_O, readinto_doc},
- {"readline", (PyCFunction)bytesio_readline, METH_VARARGS, readline_doc},
- {"readlines", (PyCFunction)bytesio_readlines, METH_VARARGS, readlines_doc},
- {"read", (PyCFunction)bytesio_read, METH_VARARGS, read_doc},
- {"getbuffer", (PyCFunction)bytesio_getbuffer, METH_NOARGS, getbuffer_doc},
- {"getvalue", (PyCFunction)bytesio_getvalue, METH_NOARGS, getval_doc},
- {"seek", (PyCFunction)bytesio_seek, METH_VARARGS, seek_doc},
- {"truncate", (PyCFunction)bytesio_truncate, METH_VARARGS, truncate_doc},
+ _IO_BYTESIO_READABLE_METHODDEF
+ _IO_BYTESIO_SEEKABLE_METHODDEF
+ _IO_BYTESIO_WRITABLE_METHODDEF
+ _IO_BYTESIO_CLOSE_METHODDEF
+ _IO_BYTESIO_FLUSH_METHODDEF
+ _IO_BYTESIO_ISATTY_METHODDEF
+ _IO_BYTESIO_TELL_METHODDEF
+ _IO_BYTESIO_WRITE_METHODDEF
+ _IO_BYTESIO_WRITELINES_METHODDEF
+ _IO_BYTESIO_READ1_METHODDEF
+ _IO_BYTESIO_READINTO_METHODDEF
+ _IO_BYTESIO_READLINE_METHODDEF
+ _IO_BYTESIO_READLINES_METHODDEF
+ _IO_BYTESIO_READ_METHODDEF
+ _IO_BYTESIO_GETBUFFER_METHODDEF
+ _IO_BYTESIO_GETVALUE_METHODDEF
+ _IO_BYTESIO_SEEK_METHODDEF
+ _IO_BYTESIO_TRUNCATE_METHODDEF
{"__getstate__", (PyCFunction)bytesio_getstate, METH_NOARGS, NULL},
{"__setstate__", (PyCFunction)bytesio_setstate, METH_O, NULL},
{"__sizeof__", (PyCFunction)bytesio_sizeof, METH_NOARGS, NULL},
{NULL, NULL} /* sentinel */
};
-PyDoc_STRVAR(bytesio_doc,
-"BytesIO([buffer]) -> object\n"
-"\n"
-"Create a buffered I/O implementation using an in-memory bytes\n"
-"buffer, ready for reading and writing.");
-
PyTypeObject PyBytesIO_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_io.BytesIO", /*tp_name*/
@@ -934,7 +1067,7 @@ PyTypeObject PyBytesIO_Type = {
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HAVE_GC, /*tp_flags*/
- bytesio_doc, /*tp_doc*/
+ _io_BytesIO___init____doc__, /*tp_doc*/
(traverseproc)bytesio_traverse, /*tp_traverse*/
(inquiry)bytesio_clear, /*tp_clear*/
0, /*tp_richcompare*/
@@ -949,7 +1082,7 @@ PyTypeObject PyBytesIO_Type = {
0, /*tp_descr_get*/
0, /*tp_descr_set*/
offsetof(bytesio, dict), /*tp_dictoffset*/
- (initproc)bytesio_init, /*tp_init*/
+ _io_BytesIO___init__, /*tp_init*/
0, /*tp_alloc*/
bytesio_new, /*tp_new*/
};
@@ -964,18 +1097,24 @@ PyTypeObject PyBytesIO_Type = {
static int
bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags)
{
- int ret;
bytesio *b = (bytesio *) obj->source;
+
if (view == NULL) {
- b->exports++;
- return 0;
+ PyErr_SetString(PyExc_BufferError,
+ "bytesiobuf_getbuffer: view==NULL argument is obsolete");
+ return -1;
}
- ret = PyBuffer_FillInfo(view, (PyObject*)obj, b->buf, b->string_size,
- 0, flags);
- if (ret >= 0) {
- b->exports++;
+ if (SHARED_BUF(b)) {
+ if (unshare_buffer(b, b->string_size) < 0)
+ return -1;
}
- return ret;
+
+ /* cannot fail if view != NULL and readonly == 0 */
+ (void)PyBuffer_FillInfo(view, (PyObject*)obj,
+ PyBytes_AS_STRING(b->buf), b->string_size,
+ 0, flags);
+ b->exports++;
+ return 0;
}
static void
diff --git a/Modules/_io/clinic/_iomodule.c.h b/Modules/_io/clinic/_iomodule.c.h
new file mode 100644
index 0000000000..a3abb93cc7
--- /dev/null
+++ b/Modules/_io/clinic/_iomodule.c.h
@@ -0,0 +1,159 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(_io_open__doc__,
+"open($module, /, file, mode=\'r\', buffering=-1, encoding=None,\n"
+" errors=None, newline=None, closefd=True, opener=None)\n"
+"--\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.");
+
+#define _IO_OPEN_METHODDEF \
+ {"open", (PyCFunction)_io_open, METH_VARARGS|METH_KEYWORDS, _io_open__doc__},
+
+static PyObject *
+_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);
+
+static PyObject *
+_io_open(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"file", "mode", "buffering", "encoding", "errors", "newline", "closefd", "opener", NULL};
+ PyObject *file;
+ const char *mode = "r";
+ int buffering = -1;
+ const char *encoding = NULL;
+ const char *errors = NULL;
+ const char *newline = NULL;
+ int closefd = 1;
+ PyObject *opener = Py_None;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|sizzziO:open", _keywords,
+ &file, &mode, &buffering, &encoding, &errors, &newline, &closefd, &opener))
+ goto exit;
+ return_value = _io_open_impl(module, file, mode, buffering, encoding, errors, newline, closefd, opener);
+
+exit:
+ return return_value;
+}
+/*[clinic end generated code: output=97cdc09bf68a8064 input=a9049054013a1b77]*/
diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h
new file mode 100644
index 0000000000..437e275730
--- /dev/null
+++ b/Modules/_io/clinic/bufferedio.c.h
@@ -0,0 +1,454 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(_io__BufferedIOBase_readinto__doc__,
+"readinto($self, buffer, /)\n"
+"--\n"
+"\n");
+
+#define _IO__BUFFEREDIOBASE_READINTO_METHODDEF \
+ {"readinto", (PyCFunction)_io__BufferedIOBase_readinto, METH_O, _io__BufferedIOBase_readinto__doc__},
+
+static PyObject *
+_io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer);
+
+static PyObject *
+_io__BufferedIOBase_readinto(PyObject *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_buffer buffer = {NULL, NULL};
+
+ if (!PyArg_Parse(arg, "w*:readinto", &buffer))
+ goto exit;
+ return_value = _io__BufferedIOBase_readinto_impl(self, &buffer);
+
+exit:
+ /* Cleanup for buffer */
+ if (buffer.obj)
+ PyBuffer_Release(&buffer);
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__BufferedIOBase_readinto1__doc__,
+"readinto1($self, buffer, /)\n"
+"--\n"
+"\n");
+
+#define _IO__BUFFEREDIOBASE_READINTO1_METHODDEF \
+ {"readinto1", (PyCFunction)_io__BufferedIOBase_readinto1, METH_O, _io__BufferedIOBase_readinto1__doc__},
+
+static PyObject *
+_io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer);
+
+static PyObject *
+_io__BufferedIOBase_readinto1(PyObject *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_buffer buffer = {NULL, NULL};
+
+ if (!PyArg_Parse(arg, "w*:readinto1", &buffer))
+ goto exit;
+ return_value = _io__BufferedIOBase_readinto1_impl(self, &buffer);
+
+exit:
+ /* Cleanup for buffer */
+ if (buffer.obj)
+ PyBuffer_Release(&buffer);
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__BufferedIOBase_detach__doc__,
+"detach($self, /)\n"
+"--\n"
+"\n"
+"Disconnect this buffer from its underlying raw stream and return it.\n"
+"\n"
+"After the raw stream has been detached, the buffer is in an unusable\n"
+"state.");
+
+#define _IO__BUFFEREDIOBASE_DETACH_METHODDEF \
+ {"detach", (PyCFunction)_io__BufferedIOBase_detach, METH_NOARGS, _io__BufferedIOBase_detach__doc__},
+
+static PyObject *
+_io__BufferedIOBase_detach_impl(PyObject *self);
+
+static PyObject *
+_io__BufferedIOBase_detach(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io__BufferedIOBase_detach_impl(self);
+}
+
+PyDoc_STRVAR(_io__Buffered_peek__doc__,
+"peek($self, size=0, /)\n"
+"--\n"
+"\n");
+
+#define _IO__BUFFERED_PEEK_METHODDEF \
+ {"peek", (PyCFunction)_io__Buffered_peek, METH_VARARGS, _io__Buffered_peek__doc__},
+
+static PyObject *
+_io__Buffered_peek_impl(buffered *self, Py_ssize_t size);
+
+static PyObject *
+_io__Buffered_peek(buffered *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t size = 0;
+
+ if (!PyArg_ParseTuple(args, "|n:peek",
+ &size))
+ goto exit;
+ return_value = _io__Buffered_peek_impl(self, size);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__Buffered_read__doc__,
+"read($self, size=-1, /)\n"
+"--\n"
+"\n");
+
+#define _IO__BUFFERED_READ_METHODDEF \
+ {"read", (PyCFunction)_io__Buffered_read, METH_VARARGS, _io__Buffered_read__doc__},
+
+static PyObject *
+_io__Buffered_read_impl(buffered *self, Py_ssize_t n);
+
+static PyObject *
+_io__Buffered_read(buffered *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t n = -1;
+
+ if (!PyArg_ParseTuple(args, "|O&:read",
+ _PyIO_ConvertSsize_t, &n))
+ goto exit;
+ return_value = _io__Buffered_read_impl(self, n);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__Buffered_read1__doc__,
+"read1($self, size, /)\n"
+"--\n"
+"\n");
+
+#define _IO__BUFFERED_READ1_METHODDEF \
+ {"read1", (PyCFunction)_io__Buffered_read1, METH_O, _io__Buffered_read1__doc__},
+
+static PyObject *
+_io__Buffered_read1_impl(buffered *self, Py_ssize_t n);
+
+static PyObject *
+_io__Buffered_read1(buffered *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t n;
+
+ if (!PyArg_Parse(arg, "n:read1", &n))
+ goto exit;
+ return_value = _io__Buffered_read1_impl(self, n);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__Buffered_readinto__doc__,
+"readinto($self, buffer, /)\n"
+"--\n"
+"\n");
+
+#define _IO__BUFFERED_READINTO_METHODDEF \
+ {"readinto", (PyCFunction)_io__Buffered_readinto, METH_O, _io__Buffered_readinto__doc__},
+
+static PyObject *
+_io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer);
+
+static PyObject *
+_io__Buffered_readinto(buffered *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_buffer buffer = {NULL, NULL};
+
+ if (!PyArg_Parse(arg, "w*:readinto", &buffer))
+ goto exit;
+ return_value = _io__Buffered_readinto_impl(self, &buffer);
+
+exit:
+ /* Cleanup for buffer */
+ if (buffer.obj)
+ PyBuffer_Release(&buffer);
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__Buffered_readinto1__doc__,
+"readinto1($self, buffer, /)\n"
+"--\n"
+"\n");
+
+#define _IO__BUFFERED_READINTO1_METHODDEF \
+ {"readinto1", (PyCFunction)_io__Buffered_readinto1, METH_O, _io__Buffered_readinto1__doc__},
+
+static PyObject *
+_io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer);
+
+static PyObject *
+_io__Buffered_readinto1(buffered *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_buffer buffer = {NULL, NULL};
+
+ if (!PyArg_Parse(arg, "w*:readinto1", &buffer))
+ goto exit;
+ return_value = _io__Buffered_readinto1_impl(self, &buffer);
+
+exit:
+ /* Cleanup for buffer */
+ if (buffer.obj)
+ PyBuffer_Release(&buffer);
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__Buffered_readline__doc__,
+"readline($self, size=-1, /)\n"
+"--\n"
+"\n");
+
+#define _IO__BUFFERED_READLINE_METHODDEF \
+ {"readline", (PyCFunction)_io__Buffered_readline, METH_VARARGS, _io__Buffered_readline__doc__},
+
+static PyObject *
+_io__Buffered_readline_impl(buffered *self, Py_ssize_t size);
+
+static PyObject *
+_io__Buffered_readline(buffered *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t size = -1;
+
+ if (!PyArg_ParseTuple(args, "|O&:readline",
+ _PyIO_ConvertSsize_t, &size))
+ goto exit;
+ return_value = _io__Buffered_readline_impl(self, size);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__Buffered_seek__doc__,
+"seek($self, target, whence=0, /)\n"
+"--\n"
+"\n");
+
+#define _IO__BUFFERED_SEEK_METHODDEF \
+ {"seek", (PyCFunction)_io__Buffered_seek, METH_VARARGS, _io__Buffered_seek__doc__},
+
+static PyObject *
+_io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence);
+
+static PyObject *
+_io__Buffered_seek(buffered *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *targetobj;
+ int whence = 0;
+
+ if (!PyArg_ParseTuple(args, "O|i:seek",
+ &targetobj, &whence))
+ goto exit;
+ return_value = _io__Buffered_seek_impl(self, targetobj, whence);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__Buffered_truncate__doc__,
+"truncate($self, pos=None, /)\n"
+"--\n"
+"\n");
+
+#define _IO__BUFFERED_TRUNCATE_METHODDEF \
+ {"truncate", (PyCFunction)_io__Buffered_truncate, METH_VARARGS, _io__Buffered_truncate__doc__},
+
+static PyObject *
+_io__Buffered_truncate_impl(buffered *self, PyObject *pos);
+
+static PyObject *
+_io__Buffered_truncate(buffered *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *pos = Py_None;
+
+ if (!PyArg_UnpackTuple(args, "truncate",
+ 0, 1,
+ &pos))
+ goto exit;
+ return_value = _io__Buffered_truncate_impl(self, pos);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_BufferedReader___init____doc__,
+"BufferedReader(raw, buffer_size=DEFAULT_BUFFER_SIZE)\n"
+"--\n"
+"\n"
+"Create a new buffered reader using the given readable raw IO object.");
+
+static int
+_io_BufferedReader___init___impl(buffered *self, PyObject *raw,
+ Py_ssize_t buffer_size);
+
+static int
+_io_BufferedReader___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int return_value = -1;
+ static char *_keywords[] = {"raw", "buffer_size", NULL};
+ PyObject *raw;
+ Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|n:BufferedReader", _keywords,
+ &raw, &buffer_size))
+ goto exit;
+ return_value = _io_BufferedReader___init___impl((buffered *)self, raw, buffer_size);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_BufferedWriter___init____doc__,
+"BufferedWriter(raw, buffer_size=DEFAULT_BUFFER_SIZE)\n"
+"--\n"
+"\n"
+"A buffer for a writeable sequential RawIO object.\n"
+"\n"
+"The constructor creates a BufferedWriter for the given writeable raw\n"
+"stream. If the buffer_size is not given, it defaults to\n"
+"DEFAULT_BUFFER_SIZE.");
+
+static int
+_io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
+ Py_ssize_t buffer_size);
+
+static int
+_io_BufferedWriter___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int return_value = -1;
+ static char *_keywords[] = {"raw", "buffer_size", NULL};
+ PyObject *raw;
+ Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|n:BufferedWriter", _keywords,
+ &raw, &buffer_size))
+ goto exit;
+ return_value = _io_BufferedWriter___init___impl((buffered *)self, raw, buffer_size);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_BufferedWriter_write__doc__,
+"write($self, buffer, /)\n"
+"--\n"
+"\n");
+
+#define _IO_BUFFEREDWRITER_WRITE_METHODDEF \
+ {"write", (PyCFunction)_io_BufferedWriter_write, METH_O, _io_BufferedWriter_write__doc__},
+
+static PyObject *
+_io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer);
+
+static PyObject *
+_io_BufferedWriter_write(buffered *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_buffer buffer = {NULL, NULL};
+
+ if (!PyArg_Parse(arg, "y*:write", &buffer))
+ goto exit;
+ return_value = _io_BufferedWriter_write_impl(self, &buffer);
+
+exit:
+ /* Cleanup for buffer */
+ if (buffer.obj)
+ PyBuffer_Release(&buffer);
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_BufferedRWPair___init____doc__,
+"BufferedRWPair(reader, writer, buffer_size=DEFAULT_BUFFER_SIZE, /)\n"
+"--\n"
+"\n"
+"A buffered reader and writer object together.\n"
+"\n"
+"A buffered reader object and buffered writer object put together to\n"
+"form a sequential IO object that can read and write. This is typically\n"
+"used with a socket or two-way pipe.\n"
+"\n"
+"reader and writer are RawIOBase objects that are readable and\n"
+"writeable respectively. If the buffer_size is omitted it defaults to\n"
+"DEFAULT_BUFFER_SIZE.");
+
+static int
+_io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader,
+ PyObject *writer, Py_ssize_t buffer_size);
+
+static int
+_io_BufferedRWPair___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int return_value = -1;
+ PyObject *reader;
+ PyObject *writer;
+ Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
+
+ if ((Py_TYPE(self) == &PyBufferedRWPair_Type) &&
+ !_PyArg_NoKeywords("BufferedRWPair", kwargs))
+ goto exit;
+ if (!PyArg_ParseTuple(args, "OO|n:BufferedRWPair",
+ &reader, &writer, &buffer_size))
+ goto exit;
+ return_value = _io_BufferedRWPair___init___impl((rwpair *)self, reader, writer, buffer_size);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_BufferedRandom___init____doc__,
+"BufferedRandom(raw, buffer_size=DEFAULT_BUFFER_SIZE)\n"
+"--\n"
+"\n"
+"A buffered interface to random access streams.\n"
+"\n"
+"The constructor creates a reader and writer for a seekable stream,\n"
+"raw, given in the first argument. If the buffer_size is omitted it\n"
+"defaults to DEFAULT_BUFFER_SIZE.");
+
+static int
+_io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
+ Py_ssize_t buffer_size);
+
+static int
+_io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int return_value = -1;
+ static char *_keywords[] = {"raw", "buffer_size", NULL};
+ PyObject *raw;
+ Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|n:BufferedRandom", _keywords,
+ &raw, &buffer_size))
+ goto exit;
+ return_value = _io_BufferedRandom___init___impl((buffered *)self, raw, buffer_size);
+
+exit:
+ return return_value;
+}
+/*[clinic end generated code: output=2bbb5e239b4ffe6f input=a9049054013a1b77]*/
diff --git a/Modules/_io/clinic/bytesio.c.h b/Modules/_io/clinic/bytesio.c.h
new file mode 100644
index 0000000000..1ab1d65a65
--- /dev/null
+++ b/Modules/_io/clinic/bytesio.c.h
@@ -0,0 +1,422 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(_io_BytesIO_readable__doc__,
+"readable($self, /)\n"
+"--\n"
+"\n"
+"Returns True if the IO object can be read.");
+
+#define _IO_BYTESIO_READABLE_METHODDEF \
+ {"readable", (PyCFunction)_io_BytesIO_readable, METH_NOARGS, _io_BytesIO_readable__doc__},
+
+static PyObject *
+_io_BytesIO_readable_impl(bytesio *self);
+
+static PyObject *
+_io_BytesIO_readable(bytesio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_BytesIO_readable_impl(self);
+}
+
+PyDoc_STRVAR(_io_BytesIO_writable__doc__,
+"writable($self, /)\n"
+"--\n"
+"\n"
+"Returns True if the IO object can be written.");
+
+#define _IO_BYTESIO_WRITABLE_METHODDEF \
+ {"writable", (PyCFunction)_io_BytesIO_writable, METH_NOARGS, _io_BytesIO_writable__doc__},
+
+static PyObject *
+_io_BytesIO_writable_impl(bytesio *self);
+
+static PyObject *
+_io_BytesIO_writable(bytesio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_BytesIO_writable_impl(self);
+}
+
+PyDoc_STRVAR(_io_BytesIO_seekable__doc__,
+"seekable($self, /)\n"
+"--\n"
+"\n"
+"Returns True if the IO object can be seeked.");
+
+#define _IO_BYTESIO_SEEKABLE_METHODDEF \
+ {"seekable", (PyCFunction)_io_BytesIO_seekable, METH_NOARGS, _io_BytesIO_seekable__doc__},
+
+static PyObject *
+_io_BytesIO_seekable_impl(bytesio *self);
+
+static PyObject *
+_io_BytesIO_seekable(bytesio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_BytesIO_seekable_impl(self);
+}
+
+PyDoc_STRVAR(_io_BytesIO_flush__doc__,
+"flush($self, /)\n"
+"--\n"
+"\n"
+"Does nothing.");
+
+#define _IO_BYTESIO_FLUSH_METHODDEF \
+ {"flush", (PyCFunction)_io_BytesIO_flush, METH_NOARGS, _io_BytesIO_flush__doc__},
+
+static PyObject *
+_io_BytesIO_flush_impl(bytesio *self);
+
+static PyObject *
+_io_BytesIO_flush(bytesio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_BytesIO_flush_impl(self);
+}
+
+PyDoc_STRVAR(_io_BytesIO_getbuffer__doc__,
+"getbuffer($self, /)\n"
+"--\n"
+"\n"
+"Get a read-write view over the contents of the BytesIO object.");
+
+#define _IO_BYTESIO_GETBUFFER_METHODDEF \
+ {"getbuffer", (PyCFunction)_io_BytesIO_getbuffer, METH_NOARGS, _io_BytesIO_getbuffer__doc__},
+
+static PyObject *
+_io_BytesIO_getbuffer_impl(bytesio *self);
+
+static PyObject *
+_io_BytesIO_getbuffer(bytesio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_BytesIO_getbuffer_impl(self);
+}
+
+PyDoc_STRVAR(_io_BytesIO_getvalue__doc__,
+"getvalue($self, /)\n"
+"--\n"
+"\n"
+"Retrieve the entire contents of the BytesIO object.");
+
+#define _IO_BYTESIO_GETVALUE_METHODDEF \
+ {"getvalue", (PyCFunction)_io_BytesIO_getvalue, METH_NOARGS, _io_BytesIO_getvalue__doc__},
+
+static PyObject *
+_io_BytesIO_getvalue_impl(bytesio *self);
+
+static PyObject *
+_io_BytesIO_getvalue(bytesio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_BytesIO_getvalue_impl(self);
+}
+
+PyDoc_STRVAR(_io_BytesIO_isatty__doc__,
+"isatty($self, /)\n"
+"--\n"
+"\n"
+"Always returns False.\n"
+"\n"
+"BytesIO objects are not connected to a TTY-like device.");
+
+#define _IO_BYTESIO_ISATTY_METHODDEF \
+ {"isatty", (PyCFunction)_io_BytesIO_isatty, METH_NOARGS, _io_BytesIO_isatty__doc__},
+
+static PyObject *
+_io_BytesIO_isatty_impl(bytesio *self);
+
+static PyObject *
+_io_BytesIO_isatty(bytesio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_BytesIO_isatty_impl(self);
+}
+
+PyDoc_STRVAR(_io_BytesIO_tell__doc__,
+"tell($self, /)\n"
+"--\n"
+"\n"
+"Current file position, an integer.");
+
+#define _IO_BYTESIO_TELL_METHODDEF \
+ {"tell", (PyCFunction)_io_BytesIO_tell, METH_NOARGS, _io_BytesIO_tell__doc__},
+
+static PyObject *
+_io_BytesIO_tell_impl(bytesio *self);
+
+static PyObject *
+_io_BytesIO_tell(bytesio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_BytesIO_tell_impl(self);
+}
+
+PyDoc_STRVAR(_io_BytesIO_read__doc__,
+"read($self, size=None, /)\n"
+"--\n"
+"\n"
+"Read at most size bytes, returned as a bytes object.\n"
+"\n"
+"If the size argument is negative, read until EOF is reached.\n"
+"Return an empty bytes object at EOF.");
+
+#define _IO_BYTESIO_READ_METHODDEF \
+ {"read", (PyCFunction)_io_BytesIO_read, METH_VARARGS, _io_BytesIO_read__doc__},
+
+static PyObject *
+_io_BytesIO_read_impl(bytesio *self, PyObject *arg);
+
+static PyObject *
+_io_BytesIO_read(bytesio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *arg = Py_None;
+
+ if (!PyArg_UnpackTuple(args, "read",
+ 0, 1,
+ &arg))
+ goto exit;
+ return_value = _io_BytesIO_read_impl(self, arg);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_BytesIO_read1__doc__,
+"read1($self, size, /)\n"
+"--\n"
+"\n"
+"Read at most size bytes, returned as a bytes object.\n"
+"\n"
+"If the size argument is negative or omitted, read until EOF is reached.\n"
+"Return an empty bytes object at EOF.");
+
+#define _IO_BYTESIO_READ1_METHODDEF \
+ {"read1", (PyCFunction)_io_BytesIO_read1, METH_O, _io_BytesIO_read1__doc__},
+
+PyDoc_STRVAR(_io_BytesIO_readline__doc__,
+"readline($self, size=None, /)\n"
+"--\n"
+"\n"
+"Next line from the file, as a bytes object.\n"
+"\n"
+"Retain newline. A non-negative size argument limits the maximum\n"
+"number of bytes to return (an incomplete line may be returned then).\n"
+"Return an empty bytes object at EOF.");
+
+#define _IO_BYTESIO_READLINE_METHODDEF \
+ {"readline", (PyCFunction)_io_BytesIO_readline, METH_VARARGS, _io_BytesIO_readline__doc__},
+
+static PyObject *
+_io_BytesIO_readline_impl(bytesio *self, PyObject *arg);
+
+static PyObject *
+_io_BytesIO_readline(bytesio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *arg = Py_None;
+
+ if (!PyArg_UnpackTuple(args, "readline",
+ 0, 1,
+ &arg))
+ goto exit;
+ return_value = _io_BytesIO_readline_impl(self, arg);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_BytesIO_readlines__doc__,
+"readlines($self, size=None, /)\n"
+"--\n"
+"\n"
+"List of bytes objects, each a line from the file.\n"
+"\n"
+"Call readline() repeatedly and return a list of the lines so read.\n"
+"The optional size argument, if given, is an approximate bound on the\n"
+"total number of bytes in the lines returned.");
+
+#define _IO_BYTESIO_READLINES_METHODDEF \
+ {"readlines", (PyCFunction)_io_BytesIO_readlines, METH_VARARGS, _io_BytesIO_readlines__doc__},
+
+static PyObject *
+_io_BytesIO_readlines_impl(bytesio *self, PyObject *arg);
+
+static PyObject *
+_io_BytesIO_readlines(bytesio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *arg = Py_None;
+
+ if (!PyArg_UnpackTuple(args, "readlines",
+ 0, 1,
+ &arg))
+ goto exit;
+ return_value = _io_BytesIO_readlines_impl(self, arg);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_BytesIO_readinto__doc__,
+"readinto($self, buffer, /)\n"
+"--\n"
+"\n"
+"Read up to len(buffer) bytes into buffer.\n"
+"\n"
+"Returns number of bytes read (0 for EOF), or None if the object\n"
+"is set not to block as has no data to read.");
+
+#define _IO_BYTESIO_READINTO_METHODDEF \
+ {"readinto", (PyCFunction)_io_BytesIO_readinto, METH_O, _io_BytesIO_readinto__doc__},
+
+static PyObject *
+_io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer);
+
+static PyObject *
+_io_BytesIO_readinto(bytesio *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_buffer buffer = {NULL, NULL};
+
+ if (!PyArg_Parse(arg, "w*:readinto", &buffer))
+ goto exit;
+ return_value = _io_BytesIO_readinto_impl(self, &buffer);
+
+exit:
+ /* Cleanup for buffer */
+ if (buffer.obj)
+ PyBuffer_Release(&buffer);
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_BytesIO_truncate__doc__,
+"truncate($self, size=None, /)\n"
+"--\n"
+"\n"
+"Truncate the file to at most size bytes.\n"
+"\n"
+"Size defaults to the current file position, as returned by tell().\n"
+"The current file position is unchanged. Returns the new size.");
+
+#define _IO_BYTESIO_TRUNCATE_METHODDEF \
+ {"truncate", (PyCFunction)_io_BytesIO_truncate, METH_VARARGS, _io_BytesIO_truncate__doc__},
+
+static PyObject *
+_io_BytesIO_truncate_impl(bytesio *self, PyObject *arg);
+
+static PyObject *
+_io_BytesIO_truncate(bytesio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *arg = Py_None;
+
+ if (!PyArg_UnpackTuple(args, "truncate",
+ 0, 1,
+ &arg))
+ goto exit;
+ return_value = _io_BytesIO_truncate_impl(self, arg);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_BytesIO_seek__doc__,
+"seek($self, pos, whence=0, /)\n"
+"--\n"
+"\n"
+"Change stream position.\n"
+"\n"
+"Seek to byte offset pos relative to position indicated by whence:\n"
+" 0 Start of stream (the default). pos should be >= 0;\n"
+" 1 Current position - pos may be negative;\n"
+" 2 End of stream - pos usually negative.\n"
+"Returns the new absolute position.");
+
+#define _IO_BYTESIO_SEEK_METHODDEF \
+ {"seek", (PyCFunction)_io_BytesIO_seek, METH_VARARGS, _io_BytesIO_seek__doc__},
+
+static PyObject *
+_io_BytesIO_seek_impl(bytesio *self, Py_ssize_t pos, int whence);
+
+static PyObject *
+_io_BytesIO_seek(bytesio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t pos;
+ int whence = 0;
+
+ if (!PyArg_ParseTuple(args, "n|i:seek",
+ &pos, &whence))
+ goto exit;
+ return_value = _io_BytesIO_seek_impl(self, pos, whence);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_BytesIO_write__doc__,
+"write($self, b, /)\n"
+"--\n"
+"\n"
+"Write bytes to file.\n"
+"\n"
+"Return the number of bytes written.");
+
+#define _IO_BYTESIO_WRITE_METHODDEF \
+ {"write", (PyCFunction)_io_BytesIO_write, METH_O, _io_BytesIO_write__doc__},
+
+PyDoc_STRVAR(_io_BytesIO_writelines__doc__,
+"writelines($self, lines, /)\n"
+"--\n"
+"\n"
+"Write lines to the file.\n"
+"\n"
+"Note that newlines are not added. lines can be any iterable object\n"
+"producing bytes-like objects. This is equivalent to calling write() for\n"
+"each element.");
+
+#define _IO_BYTESIO_WRITELINES_METHODDEF \
+ {"writelines", (PyCFunction)_io_BytesIO_writelines, METH_O, _io_BytesIO_writelines__doc__},
+
+PyDoc_STRVAR(_io_BytesIO_close__doc__,
+"close($self, /)\n"
+"--\n"
+"\n"
+"Disable all I/O operations.");
+
+#define _IO_BYTESIO_CLOSE_METHODDEF \
+ {"close", (PyCFunction)_io_BytesIO_close, METH_NOARGS, _io_BytesIO_close__doc__},
+
+static PyObject *
+_io_BytesIO_close_impl(bytesio *self);
+
+static PyObject *
+_io_BytesIO_close(bytesio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_BytesIO_close_impl(self);
+}
+
+PyDoc_STRVAR(_io_BytesIO___init____doc__,
+"BytesIO(initial_bytes=b\'\')\n"
+"--\n"
+"\n"
+"Buffered I/O implementation using an in-memory bytes buffer.");
+
+static int
+_io_BytesIO___init___impl(bytesio *self, PyObject *initvalue);
+
+static int
+_io_BytesIO___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int return_value = -1;
+ static char *_keywords[] = {"initial_bytes", NULL};
+ PyObject *initvalue = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:BytesIO", _keywords,
+ &initvalue))
+ goto exit;
+ return_value = _io_BytesIO___init___impl((bytesio *)self, initvalue);
+
+exit:
+ return return_value;
+}
+/*[clinic end generated code: output=500ccc149587fac4 input=a9049054013a1b77]*/
diff --git a/Modules/_io/clinic/fileio.c.h b/Modules/_io/clinic/fileio.c.h
new file mode 100644
index 0000000000..4a1205e933
--- /dev/null
+++ b/Modules/_io/clinic/fileio.c.h
@@ -0,0 +1,367 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(_io_FileIO_close__doc__,
+"close($self, /)\n"
+"--\n"
+"\n"
+"Close the file.\n"
+"\n"
+"A closed file cannot be used for further I/O operations. close() may be\n"
+"called more than once without error.");
+
+#define _IO_FILEIO_CLOSE_METHODDEF \
+ {"close", (PyCFunction)_io_FileIO_close, METH_NOARGS, _io_FileIO_close__doc__},
+
+static PyObject *
+_io_FileIO_close_impl(fileio *self);
+
+static PyObject *
+_io_FileIO_close(fileio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_FileIO_close_impl(self);
+}
+
+PyDoc_STRVAR(_io_FileIO___init____doc__,
+"FileIO(file, mode=\'r\', closefd=True, opener=None)\n"
+"--\n"
+"\n"
+"Open a file.\n"
+"\n"
+"The mode can be \'r\' (default), \'w\', \'x\' or \'a\' for reading,\n"
+"writing, exclusive creation or appending. The file will be created if it\n"
+"doesn\'t exist when opened for writing or appending; it will be truncated\n"
+"when opened for writing. A FileExistsError will be raised if it already\n"
+"exists when opened for creating. Opening a file for creating implies\n"
+"writing so this mode behaves in a similar way to \'w\'.Add a \'+\' to the mode\n"
+"to allow simultaneous reading and writing. A custom opener can be used by\n"
+"passing a callable as *opener*. The underlying file descriptor for the file\n"
+"object is then obtained by calling opener with (*name*, *flags*).\n"
+"*opener* must return an open file descriptor (passing os.open as *opener*\n"
+"results in functionality similar to passing None).");
+
+static int
+_io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
+ int closefd, PyObject *opener);
+
+static int
+_io_FileIO___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int return_value = -1;
+ static char *_keywords[] = {"file", "mode", "closefd", "opener", NULL};
+ PyObject *nameobj;
+ const char *mode = "r";
+ int closefd = 1;
+ PyObject *opener = Py_None;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|siO:FileIO", _keywords,
+ &nameobj, &mode, &closefd, &opener))
+ goto exit;
+ return_value = _io_FileIO___init___impl((fileio *)self, nameobj, mode, closefd, opener);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_FileIO_fileno__doc__,
+"fileno($self, /)\n"
+"--\n"
+"\n"
+"Return the underlying file descriptor (an integer).");
+
+#define _IO_FILEIO_FILENO_METHODDEF \
+ {"fileno", (PyCFunction)_io_FileIO_fileno, METH_NOARGS, _io_FileIO_fileno__doc__},
+
+static PyObject *
+_io_FileIO_fileno_impl(fileio *self);
+
+static PyObject *
+_io_FileIO_fileno(fileio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_FileIO_fileno_impl(self);
+}
+
+PyDoc_STRVAR(_io_FileIO_readable__doc__,
+"readable($self, /)\n"
+"--\n"
+"\n"
+"True if file was opened in a read mode.");
+
+#define _IO_FILEIO_READABLE_METHODDEF \
+ {"readable", (PyCFunction)_io_FileIO_readable, METH_NOARGS, _io_FileIO_readable__doc__},
+
+static PyObject *
+_io_FileIO_readable_impl(fileio *self);
+
+static PyObject *
+_io_FileIO_readable(fileio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_FileIO_readable_impl(self);
+}
+
+PyDoc_STRVAR(_io_FileIO_writable__doc__,
+"writable($self, /)\n"
+"--\n"
+"\n"
+"True if file was opened in a write mode.");
+
+#define _IO_FILEIO_WRITABLE_METHODDEF \
+ {"writable", (PyCFunction)_io_FileIO_writable, METH_NOARGS, _io_FileIO_writable__doc__},
+
+static PyObject *
+_io_FileIO_writable_impl(fileio *self);
+
+static PyObject *
+_io_FileIO_writable(fileio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_FileIO_writable_impl(self);
+}
+
+PyDoc_STRVAR(_io_FileIO_seekable__doc__,
+"seekable($self, /)\n"
+"--\n"
+"\n"
+"True if file supports random-access.");
+
+#define _IO_FILEIO_SEEKABLE_METHODDEF \
+ {"seekable", (PyCFunction)_io_FileIO_seekable, METH_NOARGS, _io_FileIO_seekable__doc__},
+
+static PyObject *
+_io_FileIO_seekable_impl(fileio *self);
+
+static PyObject *
+_io_FileIO_seekable(fileio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_FileIO_seekable_impl(self);
+}
+
+PyDoc_STRVAR(_io_FileIO_readinto__doc__,
+"readinto($self, buffer, /)\n"
+"--\n"
+"\n"
+"Same as RawIOBase.readinto().");
+
+#define _IO_FILEIO_READINTO_METHODDEF \
+ {"readinto", (PyCFunction)_io_FileIO_readinto, METH_O, _io_FileIO_readinto__doc__},
+
+static PyObject *
+_io_FileIO_readinto_impl(fileio *self, Py_buffer *buffer);
+
+static PyObject *
+_io_FileIO_readinto(fileio *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_buffer buffer = {NULL, NULL};
+
+ if (!PyArg_Parse(arg, "w*:readinto", &buffer))
+ goto exit;
+ return_value = _io_FileIO_readinto_impl(self, &buffer);
+
+exit:
+ /* Cleanup for buffer */
+ if (buffer.obj)
+ PyBuffer_Release(&buffer);
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_FileIO_readall__doc__,
+"readall($self, /)\n"
+"--\n"
+"\n"
+"Read all data from the file, returned as bytes.\n"
+"\n"
+"In non-blocking mode, returns as much as is immediately available,\n"
+"or None if no data is available. Return an empty bytes object at EOF.");
+
+#define _IO_FILEIO_READALL_METHODDEF \
+ {"readall", (PyCFunction)_io_FileIO_readall, METH_NOARGS, _io_FileIO_readall__doc__},
+
+static PyObject *
+_io_FileIO_readall_impl(fileio *self);
+
+static PyObject *
+_io_FileIO_readall(fileio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_FileIO_readall_impl(self);
+}
+
+PyDoc_STRVAR(_io_FileIO_read__doc__,
+"read($self, size=-1, /)\n"
+"--\n"
+"\n"
+"Read at most size bytes, returned as bytes.\n"
+"\n"
+"Only makes one system call, so less data may be returned than requested.\n"
+"In non-blocking mode, returns None if no data is available.\n"
+"Return an empty bytes object at EOF.");
+
+#define _IO_FILEIO_READ_METHODDEF \
+ {"read", (PyCFunction)_io_FileIO_read, METH_VARARGS, _io_FileIO_read__doc__},
+
+static PyObject *
+_io_FileIO_read_impl(fileio *self, Py_ssize_t size);
+
+static PyObject *
+_io_FileIO_read(fileio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t size = -1;
+
+ if (!PyArg_ParseTuple(args, "|O&:read",
+ _PyIO_ConvertSsize_t, &size))
+ goto exit;
+ return_value = _io_FileIO_read_impl(self, size);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_FileIO_write__doc__,
+"write($self, b, /)\n"
+"--\n"
+"\n"
+"Write bytes b to file, return number written.\n"
+"\n"
+"Only makes one system call, so not all of the data may be written.\n"
+"The number of bytes actually written is returned. In non-blocking mode,\n"
+"returns None if the write would block.");
+
+#define _IO_FILEIO_WRITE_METHODDEF \
+ {"write", (PyCFunction)_io_FileIO_write, METH_O, _io_FileIO_write__doc__},
+
+static PyObject *
+_io_FileIO_write_impl(fileio *self, Py_buffer *b);
+
+static PyObject *
+_io_FileIO_write(fileio *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_buffer b = {NULL, NULL};
+
+ if (!PyArg_Parse(arg, "y*:write", &b))
+ goto exit;
+ return_value = _io_FileIO_write_impl(self, &b);
+
+exit:
+ /* Cleanup for b */
+ if (b.obj)
+ PyBuffer_Release(&b);
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_FileIO_seek__doc__,
+"seek($self, pos, whence=0, /)\n"
+"--\n"
+"\n"
+"Move to new file position and return the file position.\n"
+"\n"
+"Argument offset is a byte count. Optional argument whence defaults to\n"
+"SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values\n"
+"are SEEK_CUR or 1 (move relative to current position, positive or negative),\n"
+"and SEEK_END or 2 (move relative to end of file, usually negative, although\n"
+"many platforms allow seeking beyond the end of a file).\n"
+"\n"
+"Note that not all file objects are seekable.");
+
+#define _IO_FILEIO_SEEK_METHODDEF \
+ {"seek", (PyCFunction)_io_FileIO_seek, METH_VARARGS, _io_FileIO_seek__doc__},
+
+static PyObject *
+_io_FileIO_seek_impl(fileio *self, PyObject *pos, int whence);
+
+static PyObject *
+_io_FileIO_seek(fileio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *pos;
+ int whence = 0;
+
+ if (!PyArg_ParseTuple(args, "O|i:seek",
+ &pos, &whence))
+ goto exit;
+ return_value = _io_FileIO_seek_impl(self, pos, whence);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_FileIO_tell__doc__,
+"tell($self, /)\n"
+"--\n"
+"\n"
+"Current file position.\n"
+"\n"
+"Can raise OSError for non seekable files.");
+
+#define _IO_FILEIO_TELL_METHODDEF \
+ {"tell", (PyCFunction)_io_FileIO_tell, METH_NOARGS, _io_FileIO_tell__doc__},
+
+static PyObject *
+_io_FileIO_tell_impl(fileio *self);
+
+static PyObject *
+_io_FileIO_tell(fileio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_FileIO_tell_impl(self);
+}
+
+#if defined(HAVE_FTRUNCATE)
+
+PyDoc_STRVAR(_io_FileIO_truncate__doc__,
+"truncate($self, size=None, /)\n"
+"--\n"
+"\n"
+"Truncate the file to at most size bytes and return the truncated size.\n"
+"\n"
+"Size defaults to the current file position, as returned by tell().\n"
+"The current file position is changed to the value of size.");
+
+#define _IO_FILEIO_TRUNCATE_METHODDEF \
+ {"truncate", (PyCFunction)_io_FileIO_truncate, METH_VARARGS, _io_FileIO_truncate__doc__},
+
+static PyObject *
+_io_FileIO_truncate_impl(fileio *self, PyObject *posobj);
+
+static PyObject *
+_io_FileIO_truncate(fileio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *posobj = NULL;
+
+ if (!PyArg_UnpackTuple(args, "truncate",
+ 0, 1,
+ &posobj))
+ goto exit;
+ return_value = _io_FileIO_truncate_impl(self, posobj);
+
+exit:
+ return return_value;
+}
+
+#endif /* defined(HAVE_FTRUNCATE) */
+
+PyDoc_STRVAR(_io_FileIO_isatty__doc__,
+"isatty($self, /)\n"
+"--\n"
+"\n"
+"True if the file is connected to a TTY device.");
+
+#define _IO_FILEIO_ISATTY_METHODDEF \
+ {"isatty", (PyCFunction)_io_FileIO_isatty, METH_NOARGS, _io_FileIO_isatty__doc__},
+
+static PyObject *
+_io_FileIO_isatty_impl(fileio *self);
+
+static PyObject *
+_io_FileIO_isatty(fileio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_FileIO_isatty_impl(self);
+}
+
+#ifndef _IO_FILEIO_TRUNCATE_METHODDEF
+ #define _IO_FILEIO_TRUNCATE_METHODDEF
+#endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */
+/*[clinic end generated code: output=b1a20b10c81add64 input=a9049054013a1b77]*/
diff --git a/Modules/_io/clinic/iobase.c.h b/Modules/_io/clinic/iobase.c.h
new file mode 100644
index 0000000000..3cea079d45
--- /dev/null
+++ b/Modules/_io/clinic/iobase.c.h
@@ -0,0 +1,279 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(_io__IOBase_tell__doc__,
+"tell($self, /)\n"
+"--\n"
+"\n"
+"Return current stream position.");
+
+#define _IO__IOBASE_TELL_METHODDEF \
+ {"tell", (PyCFunction)_io__IOBase_tell, METH_NOARGS, _io__IOBase_tell__doc__},
+
+static PyObject *
+_io__IOBase_tell_impl(PyObject *self);
+
+static PyObject *
+_io__IOBase_tell(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io__IOBase_tell_impl(self);
+}
+
+PyDoc_STRVAR(_io__IOBase_flush__doc__,
+"flush($self, /)\n"
+"--\n"
+"\n"
+"Flush write buffers, if applicable.\n"
+"\n"
+"This is not implemented for read-only and non-blocking streams.");
+
+#define _IO__IOBASE_FLUSH_METHODDEF \
+ {"flush", (PyCFunction)_io__IOBase_flush, METH_NOARGS, _io__IOBase_flush__doc__},
+
+static PyObject *
+_io__IOBase_flush_impl(PyObject *self);
+
+static PyObject *
+_io__IOBase_flush(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io__IOBase_flush_impl(self);
+}
+
+PyDoc_STRVAR(_io__IOBase_close__doc__,
+"close($self, /)\n"
+"--\n"
+"\n"
+"Flush and close the IO object.\n"
+"\n"
+"This method has no effect if the file is already closed.");
+
+#define _IO__IOBASE_CLOSE_METHODDEF \
+ {"close", (PyCFunction)_io__IOBase_close, METH_NOARGS, _io__IOBase_close__doc__},
+
+static PyObject *
+_io__IOBase_close_impl(PyObject *self);
+
+static PyObject *
+_io__IOBase_close(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io__IOBase_close_impl(self);
+}
+
+PyDoc_STRVAR(_io__IOBase_seekable__doc__,
+"seekable($self, /)\n"
+"--\n"
+"\n"
+"Return whether object supports random access.\n"
+"\n"
+"If False, seek(), tell() and truncate() will raise UnsupportedOperation.\n"
+"This method may need to do a test seek().");
+
+#define _IO__IOBASE_SEEKABLE_METHODDEF \
+ {"seekable", (PyCFunction)_io__IOBase_seekable, METH_NOARGS, _io__IOBase_seekable__doc__},
+
+static PyObject *
+_io__IOBase_seekable_impl(PyObject *self);
+
+static PyObject *
+_io__IOBase_seekable(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io__IOBase_seekable_impl(self);
+}
+
+PyDoc_STRVAR(_io__IOBase_readable__doc__,
+"readable($self, /)\n"
+"--\n"
+"\n"
+"Return whether object was opened for reading.\n"
+"\n"
+"If False, read() will raise UnsupportedOperation.");
+
+#define _IO__IOBASE_READABLE_METHODDEF \
+ {"readable", (PyCFunction)_io__IOBase_readable, METH_NOARGS, _io__IOBase_readable__doc__},
+
+static PyObject *
+_io__IOBase_readable_impl(PyObject *self);
+
+static PyObject *
+_io__IOBase_readable(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io__IOBase_readable_impl(self);
+}
+
+PyDoc_STRVAR(_io__IOBase_writable__doc__,
+"writable($self, /)\n"
+"--\n"
+"\n"
+"Return whether object was opened for writing.\n"
+"\n"
+"If False, write() will raise UnsupportedOperation.");
+
+#define _IO__IOBASE_WRITABLE_METHODDEF \
+ {"writable", (PyCFunction)_io__IOBase_writable, METH_NOARGS, _io__IOBase_writable__doc__},
+
+static PyObject *
+_io__IOBase_writable_impl(PyObject *self);
+
+static PyObject *
+_io__IOBase_writable(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io__IOBase_writable_impl(self);
+}
+
+PyDoc_STRVAR(_io__IOBase_fileno__doc__,
+"fileno($self, /)\n"
+"--\n"
+"\n"
+"Returns underlying file descriptor if one exists.\n"
+"\n"
+"An IOError is raised if the IO object does not use a file descriptor.");
+
+#define _IO__IOBASE_FILENO_METHODDEF \
+ {"fileno", (PyCFunction)_io__IOBase_fileno, METH_NOARGS, _io__IOBase_fileno__doc__},
+
+static PyObject *
+_io__IOBase_fileno_impl(PyObject *self);
+
+static PyObject *
+_io__IOBase_fileno(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io__IOBase_fileno_impl(self);
+}
+
+PyDoc_STRVAR(_io__IOBase_isatty__doc__,
+"isatty($self, /)\n"
+"--\n"
+"\n"
+"Return whether this is an \'interactive\' stream.\n"
+"\n"
+"Return False if it can\'t be determined.");
+
+#define _IO__IOBASE_ISATTY_METHODDEF \
+ {"isatty", (PyCFunction)_io__IOBase_isatty, METH_NOARGS, _io__IOBase_isatty__doc__},
+
+static PyObject *
+_io__IOBase_isatty_impl(PyObject *self);
+
+static PyObject *
+_io__IOBase_isatty(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io__IOBase_isatty_impl(self);
+}
+
+PyDoc_STRVAR(_io__IOBase_readline__doc__,
+"readline($self, size=-1, /)\n"
+"--\n"
+"\n"
+"Read and return a line from the stream.\n"
+"\n"
+"If size is specified, at most size bytes will be read.\n"
+"\n"
+"The line terminator is always b\'\\n\' for binary files; for text\n"
+"files, the newlines argument to open can be used to select the line\n"
+"terminator(s) recognized.");
+
+#define _IO__IOBASE_READLINE_METHODDEF \
+ {"readline", (PyCFunction)_io__IOBase_readline, METH_VARARGS, _io__IOBase_readline__doc__},
+
+static PyObject *
+_io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit);
+
+static PyObject *
+_io__IOBase_readline(PyObject *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t limit = -1;
+
+ if (!PyArg_ParseTuple(args, "|O&:readline",
+ _PyIO_ConvertSsize_t, &limit))
+ goto exit;
+ return_value = _io__IOBase_readline_impl(self, limit);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__IOBase_readlines__doc__,
+"readlines($self, hint=-1, /)\n"
+"--\n"
+"\n"
+"Return a list of lines from the stream.\n"
+"\n"
+"hint can be specified to control the number of lines read: no more\n"
+"lines will be read if the total size (in bytes/characters) of all\n"
+"lines so far exceeds hint.");
+
+#define _IO__IOBASE_READLINES_METHODDEF \
+ {"readlines", (PyCFunction)_io__IOBase_readlines, METH_VARARGS, _io__IOBase_readlines__doc__},
+
+static PyObject *
+_io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint);
+
+static PyObject *
+_io__IOBase_readlines(PyObject *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t hint = -1;
+
+ if (!PyArg_ParseTuple(args, "|O&:readlines",
+ _PyIO_ConvertSsize_t, &hint))
+ goto exit;
+ return_value = _io__IOBase_readlines_impl(self, hint);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__IOBase_writelines__doc__,
+"writelines($self, lines, /)\n"
+"--\n"
+"\n");
+
+#define _IO__IOBASE_WRITELINES_METHODDEF \
+ {"writelines", (PyCFunction)_io__IOBase_writelines, METH_O, _io__IOBase_writelines__doc__},
+
+PyDoc_STRVAR(_io__RawIOBase_read__doc__,
+"read($self, size=-1, /)\n"
+"--\n"
+"\n");
+
+#define _IO__RAWIOBASE_READ_METHODDEF \
+ {"read", (PyCFunction)_io__RawIOBase_read, METH_VARARGS, _io__RawIOBase_read__doc__},
+
+static PyObject *
+_io__RawIOBase_read_impl(PyObject *self, Py_ssize_t n);
+
+static PyObject *
+_io__RawIOBase_read(PyObject *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t n = -1;
+
+ if (!PyArg_ParseTuple(args, "|n:read",
+ &n))
+ goto exit;
+ return_value = _io__RawIOBase_read_impl(self, n);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io__RawIOBase_readall__doc__,
+"readall($self, /)\n"
+"--\n"
+"\n"
+"Read until EOF, using multiple read() call.");
+
+#define _IO__RAWIOBASE_READALL_METHODDEF \
+ {"readall", (PyCFunction)_io__RawIOBase_readall, METH_NOARGS, _io__RawIOBase_readall__doc__},
+
+static PyObject *
+_io__RawIOBase_readall_impl(PyObject *self);
+
+static PyObject *
+_io__RawIOBase_readall(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io__RawIOBase_readall_impl(self);
+}
+/*[clinic end generated code: output=fe034152b6884e65 input=a9049054013a1b77]*/
diff --git a/Modules/_io/clinic/stringio.c.h b/Modules/_io/clinic/stringio.c.h
new file mode 100644
index 0000000000..a8e32a3376
--- /dev/null
+++ b/Modules/_io/clinic/stringio.c.h
@@ -0,0 +1,286 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(_io_StringIO_getvalue__doc__,
+"getvalue($self, /)\n"
+"--\n"
+"\n"
+"Retrieve the entire contents of the object.");
+
+#define _IO_STRINGIO_GETVALUE_METHODDEF \
+ {"getvalue", (PyCFunction)_io_StringIO_getvalue, METH_NOARGS, _io_StringIO_getvalue__doc__},
+
+static PyObject *
+_io_StringIO_getvalue_impl(stringio *self);
+
+static PyObject *
+_io_StringIO_getvalue(stringio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_StringIO_getvalue_impl(self);
+}
+
+PyDoc_STRVAR(_io_StringIO_tell__doc__,
+"tell($self, /)\n"
+"--\n"
+"\n"
+"Tell the current file position.");
+
+#define _IO_STRINGIO_TELL_METHODDEF \
+ {"tell", (PyCFunction)_io_StringIO_tell, METH_NOARGS, _io_StringIO_tell__doc__},
+
+static PyObject *
+_io_StringIO_tell_impl(stringio *self);
+
+static PyObject *
+_io_StringIO_tell(stringio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_StringIO_tell_impl(self);
+}
+
+PyDoc_STRVAR(_io_StringIO_read__doc__,
+"read($self, size=None, /)\n"
+"--\n"
+"\n"
+"Read at most size characters, returned as a string.\n"
+"\n"
+"If the argument is negative or omitted, read until EOF\n"
+"is reached. Return an empty string at EOF.");
+
+#define _IO_STRINGIO_READ_METHODDEF \
+ {"read", (PyCFunction)_io_StringIO_read, METH_VARARGS, _io_StringIO_read__doc__},
+
+static PyObject *
+_io_StringIO_read_impl(stringio *self, PyObject *arg);
+
+static PyObject *
+_io_StringIO_read(stringio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *arg = Py_None;
+
+ if (!PyArg_UnpackTuple(args, "read",
+ 0, 1,
+ &arg))
+ goto exit;
+ return_value = _io_StringIO_read_impl(self, arg);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_StringIO_readline__doc__,
+"readline($self, size=None, /)\n"
+"--\n"
+"\n"
+"Read until newline or EOF.\n"
+"\n"
+"Returns an empty string if EOF is hit immediately.");
+
+#define _IO_STRINGIO_READLINE_METHODDEF \
+ {"readline", (PyCFunction)_io_StringIO_readline, METH_VARARGS, _io_StringIO_readline__doc__},
+
+static PyObject *
+_io_StringIO_readline_impl(stringio *self, PyObject *arg);
+
+static PyObject *
+_io_StringIO_readline(stringio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *arg = Py_None;
+
+ if (!PyArg_UnpackTuple(args, "readline",
+ 0, 1,
+ &arg))
+ goto exit;
+ return_value = _io_StringIO_readline_impl(self, arg);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_StringIO_truncate__doc__,
+"truncate($self, pos=None, /)\n"
+"--\n"
+"\n"
+"Truncate size to pos.\n"
+"\n"
+"The pos argument defaults to the current file position, as\n"
+"returned by tell(). The current file position is unchanged.\n"
+"Returns the new absolute position.");
+
+#define _IO_STRINGIO_TRUNCATE_METHODDEF \
+ {"truncate", (PyCFunction)_io_StringIO_truncate, METH_VARARGS, _io_StringIO_truncate__doc__},
+
+static PyObject *
+_io_StringIO_truncate_impl(stringio *self, PyObject *arg);
+
+static PyObject *
+_io_StringIO_truncate(stringio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *arg = Py_None;
+
+ if (!PyArg_UnpackTuple(args, "truncate",
+ 0, 1,
+ &arg))
+ goto exit;
+ return_value = _io_StringIO_truncate_impl(self, arg);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_StringIO_seek__doc__,
+"seek($self, pos, whence=0, /)\n"
+"--\n"
+"\n"
+"Change stream position.\n"
+"\n"
+"Seek to character offset pos relative to position indicated by whence:\n"
+" 0 Start of stream (the default). pos should be >= 0;\n"
+" 1 Current position - pos must be 0;\n"
+" 2 End of stream - pos must be 0.\n"
+"Returns the new absolute position.");
+
+#define _IO_STRINGIO_SEEK_METHODDEF \
+ {"seek", (PyCFunction)_io_StringIO_seek, METH_VARARGS, _io_StringIO_seek__doc__},
+
+static PyObject *
+_io_StringIO_seek_impl(stringio *self, Py_ssize_t pos, int whence);
+
+static PyObject *
+_io_StringIO_seek(stringio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t pos;
+ int whence = 0;
+
+ if (!PyArg_ParseTuple(args, "n|i:seek",
+ &pos, &whence))
+ goto exit;
+ return_value = _io_StringIO_seek_impl(self, pos, whence);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_StringIO_write__doc__,
+"write($self, s, /)\n"
+"--\n"
+"\n"
+"Write string to file.\n"
+"\n"
+"Returns the number of characters written, which is always equal to\n"
+"the length of the string.");
+
+#define _IO_STRINGIO_WRITE_METHODDEF \
+ {"write", (PyCFunction)_io_StringIO_write, METH_O, _io_StringIO_write__doc__},
+
+PyDoc_STRVAR(_io_StringIO_close__doc__,
+"close($self, /)\n"
+"--\n"
+"\n"
+"Close the IO object.\n"
+"\n"
+"Attempting any further operation after the object is closed\n"
+"will raise a ValueError.\n"
+"\n"
+"This method has no effect if the file is already closed.");
+
+#define _IO_STRINGIO_CLOSE_METHODDEF \
+ {"close", (PyCFunction)_io_StringIO_close, METH_NOARGS, _io_StringIO_close__doc__},
+
+static PyObject *
+_io_StringIO_close_impl(stringio *self);
+
+static PyObject *
+_io_StringIO_close(stringio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_StringIO_close_impl(self);
+}
+
+PyDoc_STRVAR(_io_StringIO___init____doc__,
+"StringIO(initial_value=\'\', newline=\'\\n\')\n"
+"--\n"
+"\n"
+"Text I/O implementation using an in-memory buffer.\n"
+"\n"
+"The initial_value argument sets the value of object. The newline\n"
+"argument is like the one of TextIOWrapper\'s constructor.");
+
+static int
+_io_StringIO___init___impl(stringio *self, PyObject *value,
+ PyObject *newline_obj);
+
+static int
+_io_StringIO___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int return_value = -1;
+ static char *_keywords[] = {"initial_value", "newline", NULL};
+ PyObject *value = NULL;
+ PyObject *newline_obj = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO:StringIO", _keywords,
+ &value, &newline_obj))
+ goto exit;
+ return_value = _io_StringIO___init___impl((stringio *)self, value, newline_obj);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_StringIO_readable__doc__,
+"readable($self, /)\n"
+"--\n"
+"\n"
+"Returns True if the IO object can be read.");
+
+#define _IO_STRINGIO_READABLE_METHODDEF \
+ {"readable", (PyCFunction)_io_StringIO_readable, METH_NOARGS, _io_StringIO_readable__doc__},
+
+static PyObject *
+_io_StringIO_readable_impl(stringio *self);
+
+static PyObject *
+_io_StringIO_readable(stringio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_StringIO_readable_impl(self);
+}
+
+PyDoc_STRVAR(_io_StringIO_writable__doc__,
+"writable($self, /)\n"
+"--\n"
+"\n"
+"Returns True if the IO object can be written.");
+
+#define _IO_STRINGIO_WRITABLE_METHODDEF \
+ {"writable", (PyCFunction)_io_StringIO_writable, METH_NOARGS, _io_StringIO_writable__doc__},
+
+static PyObject *
+_io_StringIO_writable_impl(stringio *self);
+
+static PyObject *
+_io_StringIO_writable(stringio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_StringIO_writable_impl(self);
+}
+
+PyDoc_STRVAR(_io_StringIO_seekable__doc__,
+"seekable($self, /)\n"
+"--\n"
+"\n"
+"Returns True if the IO object can be seeked.");
+
+#define _IO_STRINGIO_SEEKABLE_METHODDEF \
+ {"seekable", (PyCFunction)_io_StringIO_seekable, METH_NOARGS, _io_StringIO_seekable__doc__},
+
+static PyObject *
+_io_StringIO_seekable_impl(stringio *self);
+
+static PyObject *
+_io_StringIO_seekable(stringio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_StringIO_seekable_impl(self);
+}
+/*[clinic end generated code: output=f061cf3a20cd14ed input=a9049054013a1b77]*/
diff --git a/Modules/_io/clinic/textio.c.h b/Modules/_io/clinic/textio.c.h
new file mode 100644
index 0000000000..dc7e8c7584
--- /dev/null
+++ b/Modules/_io/clinic/textio.c.h
@@ -0,0 +1,456 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(_io_IncrementalNewlineDecoder___init____doc__,
+"IncrementalNewlineDecoder(decoder, translate, errors=\'strict\')\n"
+"--\n"
+"\n"
+"Codec used when reading a file in universal newlines mode.\n"
+"\n"
+"It wraps another incremental decoder, translating \\r\\n and \\r into \\n.\n"
+"It also records the types of newlines encountered. When used with\n"
+"translate=False, it ensures that the newline sequence is returned in\n"
+"one piece. When used with decoder=None, it expects unicode strings as\n"
+"decode input and translates newlines without first invoking an external\n"
+"decoder.");
+
+static int
+_io_IncrementalNewlineDecoder___init___impl(nldecoder_object *self,
+ PyObject *decoder, int translate,
+ PyObject *errors);
+
+static int
+_io_IncrementalNewlineDecoder___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int return_value = -1;
+ static char *_keywords[] = {"decoder", "translate", "errors", NULL};
+ PyObject *decoder;
+ int translate;
+ PyObject *errors = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|O:IncrementalNewlineDecoder", _keywords,
+ &decoder, &translate, &errors))
+ goto exit;
+ return_value = _io_IncrementalNewlineDecoder___init___impl((nldecoder_object *)self, decoder, translate, errors);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_IncrementalNewlineDecoder_decode__doc__,
+"decode($self, /, input, final=False)\n"
+"--\n"
+"\n");
+
+#define _IO_INCREMENTALNEWLINEDECODER_DECODE_METHODDEF \
+ {"decode", (PyCFunction)_io_IncrementalNewlineDecoder_decode, METH_VARARGS|METH_KEYWORDS, _io_IncrementalNewlineDecoder_decode__doc__},
+
+static PyObject *
+_io_IncrementalNewlineDecoder_decode_impl(nldecoder_object *self,
+ PyObject *input, int final);
+
+static PyObject *
+_io_IncrementalNewlineDecoder_decode(nldecoder_object *self, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"input", "final", NULL};
+ PyObject *input;
+ int final = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:decode", _keywords,
+ &input, &final))
+ goto exit;
+ return_value = _io_IncrementalNewlineDecoder_decode_impl(self, input, final);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_IncrementalNewlineDecoder_getstate__doc__,
+"getstate($self, /)\n"
+"--\n"
+"\n");
+
+#define _IO_INCREMENTALNEWLINEDECODER_GETSTATE_METHODDEF \
+ {"getstate", (PyCFunction)_io_IncrementalNewlineDecoder_getstate, METH_NOARGS, _io_IncrementalNewlineDecoder_getstate__doc__},
+
+static PyObject *
+_io_IncrementalNewlineDecoder_getstate_impl(nldecoder_object *self);
+
+static PyObject *
+_io_IncrementalNewlineDecoder_getstate(nldecoder_object *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_IncrementalNewlineDecoder_getstate_impl(self);
+}
+
+PyDoc_STRVAR(_io_IncrementalNewlineDecoder_setstate__doc__,
+"setstate($self, state, /)\n"
+"--\n"
+"\n");
+
+#define _IO_INCREMENTALNEWLINEDECODER_SETSTATE_METHODDEF \
+ {"setstate", (PyCFunction)_io_IncrementalNewlineDecoder_setstate, METH_O, _io_IncrementalNewlineDecoder_setstate__doc__},
+
+PyDoc_STRVAR(_io_IncrementalNewlineDecoder_reset__doc__,
+"reset($self, /)\n"
+"--\n"
+"\n");
+
+#define _IO_INCREMENTALNEWLINEDECODER_RESET_METHODDEF \
+ {"reset", (PyCFunction)_io_IncrementalNewlineDecoder_reset, METH_NOARGS, _io_IncrementalNewlineDecoder_reset__doc__},
+
+static PyObject *
+_io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self);
+
+static PyObject *
+_io_IncrementalNewlineDecoder_reset(nldecoder_object *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_IncrementalNewlineDecoder_reset_impl(self);
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper___init____doc__,
+"TextIOWrapper(buffer, encoding=None, errors=None, newline=None,\n"
+" line_buffering=False, write_through=False)\n"
+"--\n"
+"\n"
+"Character and line based layer over a BufferedIOBase object, buffer.\n"
+"\n"
+"encoding gives the name of the encoding that the stream will be\n"
+"decoded or encoded with. It defaults to locale.getpreferredencoding(False).\n"
+"\n"
+"errors determines the strictness of encoding and decoding (see\n"
+"help(codecs.Codec) or the documentation for codecs.register) and\n"
+"defaults to \"strict\".\n"
+"\n"
+"newline controls how line endings are handled. It can be None, \'\',\n"
+"\'\\n\', \'\\r\', and \'\\r\\n\'. It works as 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 line_buffering is True, a call to flush is implied when a call to\n"
+"write contains a newline character.");
+
+static int
+_io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
+ const char *encoding, const char *errors,
+ const char *newline, int line_buffering,
+ int write_through);
+
+static int
+_io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int return_value = -1;
+ static char *_keywords[] = {"buffer", "encoding", "errors", "newline", "line_buffering", "write_through", NULL};
+ PyObject *buffer;
+ const char *encoding = NULL;
+ const char *errors = NULL;
+ const char *newline = NULL;
+ int line_buffering = 0;
+ int write_through = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|zzzii:TextIOWrapper", _keywords,
+ &buffer, &encoding, &errors, &newline, &line_buffering, &write_through))
+ goto exit;
+ return_value = _io_TextIOWrapper___init___impl((textio *)self, buffer, encoding, errors, newline, line_buffering, write_through);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_detach__doc__,
+"detach($self, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_DETACH_METHODDEF \
+ {"detach", (PyCFunction)_io_TextIOWrapper_detach, METH_NOARGS, _io_TextIOWrapper_detach__doc__},
+
+static PyObject *
+_io_TextIOWrapper_detach_impl(textio *self);
+
+static PyObject *
+_io_TextIOWrapper_detach(textio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_TextIOWrapper_detach_impl(self);
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_write__doc__,
+"write($self, text, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_WRITE_METHODDEF \
+ {"write", (PyCFunction)_io_TextIOWrapper_write, METH_O, _io_TextIOWrapper_write__doc__},
+
+static PyObject *
+_io_TextIOWrapper_write_impl(textio *self, PyObject *text);
+
+static PyObject *
+_io_TextIOWrapper_write(textio *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ PyObject *text;
+
+ if (!PyArg_Parse(arg, "U:write", &text))
+ goto exit;
+ return_value = _io_TextIOWrapper_write_impl(self, text);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_read__doc__,
+"read($self, size=-1, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_READ_METHODDEF \
+ {"read", (PyCFunction)_io_TextIOWrapper_read, METH_VARARGS, _io_TextIOWrapper_read__doc__},
+
+static PyObject *
+_io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n);
+
+static PyObject *
+_io_TextIOWrapper_read(textio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t n = -1;
+
+ if (!PyArg_ParseTuple(args, "|O&:read",
+ _PyIO_ConvertSsize_t, &n))
+ goto exit;
+ return_value = _io_TextIOWrapper_read_impl(self, n);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_readline__doc__,
+"readline($self, size=-1, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_READLINE_METHODDEF \
+ {"readline", (PyCFunction)_io_TextIOWrapper_readline, METH_VARARGS, _io_TextIOWrapper_readline__doc__},
+
+static PyObject *
+_io_TextIOWrapper_readline_impl(textio *self, Py_ssize_t size);
+
+static PyObject *
+_io_TextIOWrapper_readline(textio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t size = -1;
+
+ if (!PyArg_ParseTuple(args, "|n:readline",
+ &size))
+ goto exit;
+ return_value = _io_TextIOWrapper_readline_impl(self, size);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_seek__doc__,
+"seek($self, cookie, whence=0, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_SEEK_METHODDEF \
+ {"seek", (PyCFunction)_io_TextIOWrapper_seek, METH_VARARGS, _io_TextIOWrapper_seek__doc__},
+
+static PyObject *
+_io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence);
+
+static PyObject *
+_io_TextIOWrapper_seek(textio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *cookieObj;
+ int whence = 0;
+
+ if (!PyArg_ParseTuple(args, "O|i:seek",
+ &cookieObj, &whence))
+ goto exit;
+ return_value = _io_TextIOWrapper_seek_impl(self, cookieObj, whence);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_tell__doc__,
+"tell($self, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_TELL_METHODDEF \
+ {"tell", (PyCFunction)_io_TextIOWrapper_tell, METH_NOARGS, _io_TextIOWrapper_tell__doc__},
+
+static PyObject *
+_io_TextIOWrapper_tell_impl(textio *self);
+
+static PyObject *
+_io_TextIOWrapper_tell(textio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_TextIOWrapper_tell_impl(self);
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_truncate__doc__,
+"truncate($self, pos=None, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_TRUNCATE_METHODDEF \
+ {"truncate", (PyCFunction)_io_TextIOWrapper_truncate, METH_VARARGS, _io_TextIOWrapper_truncate__doc__},
+
+static PyObject *
+_io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos);
+
+static PyObject *
+_io_TextIOWrapper_truncate(textio *self, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *pos = Py_None;
+
+ if (!PyArg_UnpackTuple(args, "truncate",
+ 0, 1,
+ &pos))
+ goto exit;
+ return_value = _io_TextIOWrapper_truncate_impl(self, pos);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_fileno__doc__,
+"fileno($self, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_FILENO_METHODDEF \
+ {"fileno", (PyCFunction)_io_TextIOWrapper_fileno, METH_NOARGS, _io_TextIOWrapper_fileno__doc__},
+
+static PyObject *
+_io_TextIOWrapper_fileno_impl(textio *self);
+
+static PyObject *
+_io_TextIOWrapper_fileno(textio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_TextIOWrapper_fileno_impl(self);
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_seekable__doc__,
+"seekable($self, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_SEEKABLE_METHODDEF \
+ {"seekable", (PyCFunction)_io_TextIOWrapper_seekable, METH_NOARGS, _io_TextIOWrapper_seekable__doc__},
+
+static PyObject *
+_io_TextIOWrapper_seekable_impl(textio *self);
+
+static PyObject *
+_io_TextIOWrapper_seekable(textio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_TextIOWrapper_seekable_impl(self);
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_readable__doc__,
+"readable($self, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_READABLE_METHODDEF \
+ {"readable", (PyCFunction)_io_TextIOWrapper_readable, METH_NOARGS, _io_TextIOWrapper_readable__doc__},
+
+static PyObject *
+_io_TextIOWrapper_readable_impl(textio *self);
+
+static PyObject *
+_io_TextIOWrapper_readable(textio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_TextIOWrapper_readable_impl(self);
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_writable__doc__,
+"writable($self, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_WRITABLE_METHODDEF \
+ {"writable", (PyCFunction)_io_TextIOWrapper_writable, METH_NOARGS, _io_TextIOWrapper_writable__doc__},
+
+static PyObject *
+_io_TextIOWrapper_writable_impl(textio *self);
+
+static PyObject *
+_io_TextIOWrapper_writable(textio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_TextIOWrapper_writable_impl(self);
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_isatty__doc__,
+"isatty($self, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_ISATTY_METHODDEF \
+ {"isatty", (PyCFunction)_io_TextIOWrapper_isatty, METH_NOARGS, _io_TextIOWrapper_isatty__doc__},
+
+static PyObject *
+_io_TextIOWrapper_isatty_impl(textio *self);
+
+static PyObject *
+_io_TextIOWrapper_isatty(textio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_TextIOWrapper_isatty_impl(self);
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_flush__doc__,
+"flush($self, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_FLUSH_METHODDEF \
+ {"flush", (PyCFunction)_io_TextIOWrapper_flush, METH_NOARGS, _io_TextIOWrapper_flush__doc__},
+
+static PyObject *
+_io_TextIOWrapper_flush_impl(textio *self);
+
+static PyObject *
+_io_TextIOWrapper_flush(textio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_TextIOWrapper_flush_impl(self);
+}
+
+PyDoc_STRVAR(_io_TextIOWrapper_close__doc__,
+"close($self, /)\n"
+"--\n"
+"\n");
+
+#define _IO_TEXTIOWRAPPER_CLOSE_METHODDEF \
+ {"close", (PyCFunction)_io_TextIOWrapper_close, METH_NOARGS, _io_TextIOWrapper_close__doc__},
+
+static PyObject *
+_io_TextIOWrapper_close_impl(textio *self);
+
+static PyObject *
+_io_TextIOWrapper_close(textio *self, PyObject *Py_UNUSED(ignored))
+{
+ return _io_TextIOWrapper_close_impl(self);
+}
+/*[clinic end generated code: output=690608f85aab8ba5 input=a9049054013a1b77]*/
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index 74508a7f42..12e37bbbbe 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -43,6 +43,19 @@
#define SMALLCHUNK BUFSIZ
#endif
+/*[clinic input]
+module _io
+class _io.FileIO "fileio *" "&PyFileIO_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1c77708b41fda70c]*/
+
+/*[python input]
+class io_ssize_t_converter(CConverter):
+ type = 'Py_ssize_t'
+ converter = '_PyIO_ConvertSsize_t'
+[python start generated code]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/
+
typedef struct {
PyObject_HEAD
int fd;
@@ -53,6 +66,7 @@ typedef struct {
signed int seekable : 2; /* -1 means unknown */
unsigned int closefd : 1;
char finalizing;
+ unsigned int blksize;
PyObject *weakreflist;
PyObject *dict;
} fileio;
@@ -106,9 +120,11 @@ internal_close(fileio *self)
/* fd is accessible and someone else may have closed it */
if (_PyVerify_fd(fd)) {
Py_BEGIN_ALLOW_THREADS
+ _Py_BEGIN_SUPPRESS_IPH
err = close(fd);
if (err < 0)
save_errno = errno;
+ _Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
} else {
save_errno = errno;
@@ -123,8 +139,18 @@ internal_close(fileio *self)
return 0;
}
+/*[clinic input]
+_io.FileIO.close
+
+Close the file.
+
+A closed file cannot be used for further I/O operations. close() may be
+called more than once without error.
+[clinic start generated code]*/
+
static PyObject *
-fileio_close(fileio *self)
+_io_FileIO_close_impl(fileio *self)
+/*[clinic end generated code: output=7737a319ef3bad0b input=f35231760d54a522]*/
{
PyObject *res;
PyObject *exc, *val, *tb;
@@ -168,6 +194,7 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self->writable = 0;
self->appending = 0;
self->seekable = -1;
+ self->blksize = 0;
self->closefd = 1;
self->weakreflist = NULL;
}
@@ -175,57 +202,40 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject *) self;
}
-/* On Unix, open will succeed for directories.
- In Python, there should be no file objects referring to
- directories, so we need a check. */
-
-static int
-dircheck(fileio* self, PyObject *nameobj)
-{
-#if defined(HAVE_FSTAT) && defined(S_ISDIR) && defined(EISDIR)
- struct stat buf;
- if (self->fd < 0)
- return 0;
- if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
- errno = EISDIR;
- PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj);
- return -1;
- }
-#endif
- return 0;
-}
-
-static int
-check_fd(int fd)
-{
-#if defined(HAVE_FSTAT)
- struct stat buf;
- if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) {
- PyObject *exc;
- char *msg = strerror(EBADF);
- exc = PyObject_CallFunction(PyExc_OSError, "(is)",
- EBADF, msg);
- PyErr_SetObject(PyExc_OSError, exc);
- Py_XDECREF(exc);
- return -1;
- }
-#endif
- return 0;
-}
-
#ifdef O_CLOEXEC
extern int _Py_open_cloexec_works;
#endif
+/*[clinic input]
+_io.FileIO.__init__
+ file as nameobj: object
+ mode: str = "r"
+ closefd: int(c_default="1") = True
+ opener: object = None
+
+Open a file.
+
+The mode can be 'r' (default), 'w', 'x' or 'a' for reading,
+writing, exclusive creation or appending. The file will be created if it
+doesn't exist when opened for writing or appending; it will be truncated
+when opened for writing. A FileExistsError will be raised if it already
+exists when opened for creating. Opening a file for creating implies
+writing so this mode behaves in a similar way to 'w'.Add a '+' to the mode
+to allow simultaneous reading and writing. 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 (*name*, *flags*).
+*opener* must return an open file descriptor (passing os.open as *opener*
+results in functionality similar to passing None).
+[clinic start generated code]*/
+
static int
-fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
+_io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
+ int closefd, PyObject *opener)
+/*[clinic end generated code: output=23413f68e6484bbd input=193164e293d6c097]*/
{
- fileio *self = (fileio *) oself;
- static char *kwlist[] = {"file", "mode", "closefd", "opener", NULL};
const char *name = NULL;
- PyObject *nameobj, *stringobj = NULL, *opener = Py_None;
- char *mode = "r";
- char *s;
+ PyObject *stringobj = NULL;
+ const char *s;
#ifdef MS_WINDOWS
Py_UNICODE *widename = NULL;
#endif
@@ -233,15 +243,16 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
int rwa = 0, plus = 0;
int flags = 0;
int fd = -1;
- int closefd = 1;
int fd_is_own = 0;
#ifdef O_CLOEXEC
int *atomic_flag_works = &_Py_open_cloexec_works;
#elif !defined(MS_WINDOWS)
int *atomic_flag_works = NULL;
#endif
+ struct _Py_stat_struct fdfstat;
+ int async_err = 0;
- assert(PyFileIO_Check(oself));
+ assert(PyFileIO_Check(self));
if (self->fd >= 0) {
if (self->closefd) {
/* Have to close the existing file first. */
@@ -252,11 +263,6 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
self->fd = -1;
}
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|siO:fileio",
- kwlist, &nameobj, &mode, &closefd,
- &opener))
- return -1;
-
if (PyFloat_Check(nameobj)) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float");
@@ -280,7 +286,7 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
if (widename == NULL)
return -1;
if (wcslen(widename) != length) {
- PyErr_SetString(PyExc_TypeError, "embedded NUL character");
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
return -1;
}
} else
@@ -366,8 +372,6 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
#endif
if (fd >= 0) {
- if (check_fd(fd))
- goto error;
self->fd = fd;
self->closefd = closefd;
}
@@ -381,15 +385,20 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
errno = 0;
if (opener == Py_None) {
- Py_BEGIN_ALLOW_THREADS
+ do {
+ Py_BEGIN_ALLOW_THREADS
#ifdef MS_WINDOWS
- if (widename != NULL)
- self->fd = _wopen(widename, flags, 0666);
- else
+ if (widename != NULL)
+ self->fd = _wopen(widename, flags, 0666);
+ else
#endif
- self->fd = open(name, flags, 0666);
+ self->fd = open(name, flags, 0666);
+ Py_END_ALLOW_THREADS
+ } while (self->fd < 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
- Py_END_ALLOW_THREADS
+ if (async_err)
+ goto error;
}
else {
PyObject *fdobj;
@@ -427,8 +436,24 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
goto error;
#endif
}
- if (dircheck(self, nameobj) < 0)
+
+ self->blksize = DEFAULT_BUFFER_SIZE;
+ if (_Py_fstat(self->fd, &fdfstat) < 0)
+ goto error;
+#if defined(S_ISDIR) && defined(EISDIR)
+ /* On Unix, open will succeed for directories.
+ In Python, there should be no file objects referring to
+ directories, so we need a check. */
+ if (S_ISDIR(fdfstat.st_mode)) {
+ errno = EISDIR;
+ PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj);
goto error;
+ }
+#endif /* defined(S_ISDIR) */
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+ if (fdfstat.st_blksize > 1)
+ self->blksize = fdfstat.st_blksize;
+#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
/* don't translate newlines (\r\n <=> \n) */
@@ -506,32 +531,60 @@ err_mode(char *action)
return NULL;
}
+/*[clinic input]
+_io.FileIO.fileno
+
+Return the underlying file descriptor (an integer).
+[clinic start generated code]*/
+
static PyObject *
-fileio_fileno(fileio *self)
+_io_FileIO_fileno_impl(fileio *self)
+/*[clinic end generated code: output=a9626ce5398ece90 input=0b9b2de67335ada3]*/
{
if (self->fd < 0)
return err_closed();
return PyLong_FromLong((long) self->fd);
}
+/*[clinic input]
+_io.FileIO.readable
+
+True if file was opened in a read mode.
+[clinic start generated code]*/
+
static PyObject *
-fileio_readable(fileio *self)
+_io_FileIO_readable_impl(fileio *self)
+/*[clinic end generated code: output=640744a6150fe9ba input=a3fdfed6eea721c5]*/
{
if (self->fd < 0)
return err_closed();
return PyBool_FromLong((long) self->readable);
}
+/*[clinic input]
+_io.FileIO.writable
+
+True if file was opened in a write mode.
+[clinic start generated code]*/
+
static PyObject *
-fileio_writable(fileio *self)
+_io_FileIO_writable_impl(fileio *self)
+/*[clinic end generated code: output=96cefc5446e89977 input=c204a808ca2e1748]*/
{
if (self->fd < 0)
return err_closed();
return PyBool_FromLong((long) self->writable);
}
+/*[clinic input]
+_io.FileIO.seekable
+
+True if file supports random-access.
+[clinic start generated code]*/
+
static PyObject *
-fileio_seekable(fileio *self)
+_io_FileIO_seekable_impl(fileio *self)
+/*[clinic end generated code: output=47909ca0a42e9287 input=c8e5554d2fd63c7f]*/
{
if (self->fd < 0)
return err_closed();
@@ -548,11 +601,19 @@ fileio_seekable(fileio *self)
return PyBool_FromLong((long) self->seekable);
}
+/*[clinic input]
+_io.FileIO.readinto
+ buffer: Py_buffer(accept={rwbuffer})
+ /
+
+Same as RawIOBase.readinto().
+[clinic start generated code]*/
+
static PyObject *
-fileio_readinto(fileio *self, PyObject *args)
+_io_FileIO_readinto_impl(fileio *self, Py_buffer *buffer)
+/*[clinic end generated code: output=b01a5a22c8415cb4 input=4721d7b68b154eaf]*/
{
- Py_buffer pbuf;
- Py_ssize_t n, len;
+ Py_ssize_t n;
int err;
if (self->fd < 0)
@@ -560,48 +621,21 @@ fileio_readinto(fileio *self, PyObject *args)
if (!self->readable)
return err_mode("reading");
- if (!PyArg_ParseTuple(args, "w*", &pbuf))
- return NULL;
-
- if (_PyVerify_fd(self->fd)) {
- len = pbuf.len;
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
-#ifdef MS_WINDOWS
- if (len > INT_MAX)
- len = INT_MAX;
- n = read(self->fd, pbuf.buf, (int)len);
-#else
- n = read(self->fd, pbuf.buf, len);
-#endif
- Py_END_ALLOW_THREADS
- } else
- n = -1;
+ n = _Py_read(self->fd, buffer->buf, buffer->len);
+ /* copy errno because PyBuffer_Release() can indirectly modify it */
err = errno;
- PyBuffer_Release(&pbuf);
- if (n < 0) {
- if (err == EAGAIN)
+
+ if (n == -1) {
+ if (err == EAGAIN) {
+ PyErr_Clear();
Py_RETURN_NONE;
- errno = err;
- PyErr_SetFromErrno(PyExc_IOError);
+ }
return NULL;
}
return PyLong_FromSsize_t(n);
}
-#ifndef HAVE_FSTAT
-
-static PyObject *
-fileio_readall(fileio *self)
-{
- _Py_IDENTIFIER(readall);
- return _PyObject_CallMethodId((PyObject*)&PyRawIOBase_Type,
- &PyId_readall, "O", self);
-}
-
-#else
-
static size_t
new_buffersize(fileio *self, size_t currentsize)
{
@@ -621,10 +655,20 @@ new_buffersize(fileio *self, size_t currentsize)
return addend + currentsize;
}
+/*[clinic input]
+_io.FileIO.readall
+
+Read all data from the file, returned as bytes.
+
+In non-blocking mode, returns as much as is immediately available,
+or None if no data is available. Return an empty bytes object at EOF.
+[clinic start generated code]*/
+
static PyObject *
-fileio_readall(fileio *self)
+_io_FileIO_readall_impl(fileio *self)
+/*[clinic end generated code: output=faa0292b213b4022 input=dbdc137f55602834]*/
{
- struct stat st;
+ struct _Py_stat_struct status;
Py_off_t pos, end;
PyObject *result;
Py_ssize_t bytes_read = 0;
@@ -636,13 +680,16 @@ fileio_readall(fileio *self)
if (!_PyVerify_fd(self->fd))
return PyErr_SetFromErrno(PyExc_IOError);
+ _Py_BEGIN_SUPPRESS_IPH
#ifdef MS_WINDOWS
pos = _lseeki64(self->fd, 0L, SEEK_CUR);
#else
pos = lseek(self->fd, 0L, SEEK_CUR);
#endif
- if (fstat(self->fd, &st) == 0)
- end = st.st_size;
+ _Py_END_SUPPRESS_IPH
+
+ if (_Py_fstat_noraise(self->fd, &status) == 0)
+ end = status.st_size;
else
end = (Py_off_t)-1;
@@ -676,35 +723,22 @@ fileio_readall(fileio *self)
return NULL;
}
}
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- n = bufsize - bytes_read;
-#ifdef MS_WINDOWS
- if (n > INT_MAX)
- n = INT_MAX;
- n = read(self->fd, PyBytes_AS_STRING(result) + bytes_read, (int)n);
-#else
- n = read(self->fd, PyBytes_AS_STRING(result) + bytes_read, n);
-#endif
- Py_END_ALLOW_THREADS
+
+ n = _Py_read(self->fd,
+ PyBytes_AS_STRING(result) + bytes_read,
+ bufsize - bytes_read);
+
if (n == 0)
break;
- if (n < 0) {
- if (errno == EINTR) {
- if (PyErr_CheckSignals()) {
- Py_DECREF(result);
- return NULL;
- }
- continue;
- }
+ if (n == -1) {
if (errno == EAGAIN) {
+ PyErr_Clear();
if (bytes_read > 0)
break;
Py_DECREF(result);
Py_RETURN_NONE;
}
Py_DECREF(result);
- PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
bytes_read += n;
@@ -718,14 +752,24 @@ fileio_readall(fileio *self)
return result;
}
-#endif /* HAVE_FSTAT */
+/*[clinic input]
+_io.FileIO.read
+ size: io_ssize_t = -1
+ /
+
+Read at most size bytes, returned as bytes.
+
+Only makes one system call, so less data may be returned than requested.
+In non-blocking mode, returns None if no data is available.
+Return an empty bytes object at EOF.
+[clinic start generated code]*/
static PyObject *
-fileio_read(fileio *self, PyObject *args)
+_io_FileIO_read_impl(fileio *self, Py_ssize_t size)
+/*[clinic end generated code: output=42528d39dd0ca641 input=5c6caa5490c13a9b]*/
{
char *ptr;
Py_ssize_t n;
- Py_ssize_t size = -1;
PyObject *bytes;
if (self->fd < 0)
@@ -733,41 +777,29 @@ fileio_read(fileio *self, PyObject *args)
if (!self->readable)
return err_mode("reading");
- if (!PyArg_ParseTuple(args, "|O&", &_PyIO_ConvertSsize_t, &size))
- return NULL;
-
- if (size < 0) {
- return fileio_readall(self);
- }
+ if (size < 0)
+ return _io_FileIO_readall_impl(self);
#ifdef MS_WINDOWS
+ /* On Windows, the count parameter of read() is an int */
if (size > INT_MAX)
size = INT_MAX;
#endif
+
bytes = PyBytes_FromStringAndSize(NULL, size);
if (bytes == NULL)
return NULL;
ptr = PyBytes_AS_STRING(bytes);
- if (_PyVerify_fd(self->fd)) {
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
-#ifdef MS_WINDOWS
- n = read(self->fd, ptr, (int)size);
-#else
- n = read(self->fd, ptr, size);
-#endif
- Py_END_ALLOW_THREADS
- } else
- n = -1;
-
- if (n < 0) {
+ n = _Py_read(self->fd, ptr, size);
+ if (n == -1) {
+ /* copy errno because Py_DECREF() can indirectly modify it */
int err = errno;
Py_DECREF(bytes);
- if (err == EAGAIN)
+ if (err == EAGAIN) {
+ PyErr_Clear();
Py_RETURN_NONE;
- errno = err;
- PyErr_SetFromErrno(PyExc_IOError);
+ }
return NULL;
}
@@ -781,11 +813,23 @@ fileio_read(fileio *self, PyObject *args)
return (PyObject *) bytes;
}
+/*[clinic input]
+_io.FileIO.write
+ b: Py_buffer
+ /
+
+Write bytes b to file, return number written.
+
+Only makes one system call, so not all of the data may be written.
+The number of bytes actually written is returned. In non-blocking mode,
+returns None if the write would block.
+[clinic start generated code]*/
+
static PyObject *
-fileio_write(fileio *self, PyObject *args)
+_io_FileIO_write_impl(fileio *self, Py_buffer *b)
+/*[clinic end generated code: output=b4059db3d363a2f7 input=ffbd8834f447ac31]*/
{
- Py_buffer pbuf;
- Py_ssize_t n, len;
+ Py_ssize_t n;
int err;
if (self->fd < 0)
@@ -793,39 +837,15 @@ fileio_write(fileio *self, PyObject *args)
if (!self->writable)
return err_mode("writing");
- if (!PyArg_ParseTuple(args, "y*", &pbuf))
- return NULL;
-
- if (_PyVerify_fd(self->fd)) {
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- len = pbuf.len;
-#ifdef MS_WINDOWS
- if (len > 32767 && isatty(self->fd)) {
- /* Issue #11395: the Windows console returns an error (12: not
- enough space error) on writing into stdout if stdout mode is
- binary and the length is greater than 66,000 bytes (or less,
- depending on heap usage). */
- len = 32767;
- }
- else if (len > INT_MAX)
- len = INT_MAX;
- n = write(self->fd, pbuf.buf, (int)len);
-#else
- n = write(self->fd, pbuf.buf, len);
-#endif
- Py_END_ALLOW_THREADS
- } else
- n = -1;
+ n = _Py_write(self->fd, b->buf, b->len);
+ /* copy errno because PyBuffer_Release() can indirectly modify it */
err = errno;
- PyBuffer_Release(&pbuf);
-
if (n < 0) {
- if (err == EAGAIN)
+ if (err == EAGAIN) {
+ PyErr_Clear();
Py_RETURN_NONE;
- errno = err;
- PyErr_SetFromErrno(PyExc_IOError);
+ }
return NULL;
}
@@ -873,11 +893,13 @@ portable_lseek(int fd, PyObject *posobj, int whence)
if (_PyVerify_fd(fd)) {
Py_BEGIN_ALLOW_THREADS
+ _Py_BEGIN_SUPPRESS_IPH
#ifdef MS_WINDOWS
res = _lseeki64(fd, pos, whence);
#else
res = lseek(fd, pos, whence);
#endif
+ _Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
} else
res = -1;
@@ -891,23 +913,44 @@ portable_lseek(int fd, PyObject *posobj, int whence)
#endif
}
+/*[clinic input]
+_io.FileIO.seek
+ pos: object
+ whence: int = 0
+ /
+
+Move to new file position and return the file position.
+
+Argument offset is a byte count. Optional argument whence defaults to
+SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values
+are SEEK_CUR or 1 (move relative to current position, positive or negative),
+and SEEK_END or 2 (move relative to end of file, usually negative, although
+many platforms allow seeking beyond the end of a file).
+
+Note that not all file objects are seekable.
+[clinic start generated code]*/
+
static PyObject *
-fileio_seek(fileio *self, PyObject *args)
+_io_FileIO_seek_impl(fileio *self, PyObject *pos, int whence)
+/*[clinic end generated code: output=c976acdf054e6655 input=0439194b0774d454]*/
{
- PyObject *posobj;
- int whence = 0;
-
if (self->fd < 0)
return err_closed();
- if (!PyArg_ParseTuple(args, "O|i", &posobj, &whence))
- return NULL;
-
- return portable_lseek(self->fd, posobj, whence);
+ return portable_lseek(self->fd, pos, whence);
}
+/*[clinic input]
+_io.FileIO.tell
+
+Current file position.
+
+Can raise OSError for non seekable files.
+[clinic start generated code]*/
+
static PyObject *
-fileio_tell(fileio *self, PyObject *args)
+_io_FileIO_tell_impl(fileio *self)
+/*[clinic end generated code: output=ffe2147058809d0b input=807e24ead4cec2f9]*/
{
if (self->fd < 0)
return err_closed();
@@ -916,13 +959,22 @@ fileio_tell(fileio *self, PyObject *args)
}
#ifdef HAVE_FTRUNCATE
+/*[clinic input]
+_io.FileIO.truncate
+ size as posobj: object = NULL
+ /
+
+Truncate the file to at most size bytes and return the truncated size.
+
+Size defaults to the current file position, as returned by tell().
+The current file position is changed to the value of size.
+[clinic start generated code]*/
+
static PyObject *
-fileio_truncate(fileio *self, PyObject *args)
+_io_FileIO_truncate_impl(fileio *self, PyObject *posobj)
+/*[clinic end generated code: output=e49ca7a916c176fa input=9026af44686b7318]*/
{
- PyObject *posobj = NULL; /* the new size wanted by the user */
-#ifndef MS_WINDOWS
Py_off_t pos;
-#endif
int ret;
int fd;
@@ -932,9 +984,6 @@ fileio_truncate(fileio *self, PyObject *args)
if (!self->writable)
return err_mode("writing");
- if (!PyArg_ParseTuple(args, "|O", &posobj))
- return NULL;
-
if (posobj == Py_None || posobj == NULL) {
/* Get the current position. */
posobj = portable_lseek(fd, NULL, 1);
@@ -945,52 +994,6 @@ fileio_truncate(fileio *self, PyObject *args)
Py_INCREF(posobj);
}
-#ifdef MS_WINDOWS
- /* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
- so don't even try using it. */
- {
- PyObject *oldposobj, *tempposobj;
- HANDLE hFile;
-
- /* we save the file pointer position */
- oldposobj = portable_lseek(fd, NULL, 1);
- if (oldposobj == NULL) {
- Py_DECREF(posobj);
- return NULL;
- }
-
- /* we then move to the truncation position */
- tempposobj = portable_lseek(fd, posobj, 0);
- if (tempposobj == NULL) {
- Py_DECREF(oldposobj);
- Py_DECREF(posobj);
- return NULL;
- }
- Py_DECREF(tempposobj);
-
- /* Truncate. Note that this may grow the file! */
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- hFile = (HANDLE)_get_osfhandle(fd);
- ret = hFile == (HANDLE)-1; /* testing for INVALID_HANDLE value */
- if (ret == 0) {
- ret = SetEndOfFile(hFile) == 0;
- if (ret)
- errno = EACCES;
- }
- Py_END_ALLOW_THREADS
-
- /* we restore the file pointer position in any case */
- tempposobj = portable_lseek(fd, oldposobj, 0);
- Py_DECREF(oldposobj);
- if (tempposobj == NULL) {
- Py_DECREF(posobj);
- return NULL;
- }
- Py_DECREF(tempposobj);
- }
-#else
-
#if defined(HAVE_LARGEFILE_SUPPORT)
pos = PyLong_AsLongLong(posobj);
#else
@@ -1002,12 +1005,16 @@ fileio_truncate(fileio *self, PyObject *args)
}
Py_BEGIN_ALLOW_THREADS
+ _Py_BEGIN_SUPPRESS_IPH
errno = 0;
+#ifdef MS_WINDOWS
+ ret = _chsize_s(fd, pos);
+#else
ret = ftruncate(fd, pos);
+#endif
+ _Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
-#endif /* !MS_WINDOWS */
-
if (ret != 0) {
Py_DECREF(posobj);
PyErr_SetFromErrno(PyExc_IOError);
@@ -1057,26 +1064,40 @@ fileio_repr(fileio *self)
PyErr_Clear();
else
return NULL;
- res = PyUnicode_FromFormat("<_io.FileIO fd=%d mode='%s'>",
- self->fd, mode_string(self));
+ res = PyUnicode_FromFormat(
+ "<_io.FileIO fd=%d mode='%s' closefd=%s>",
+ self->fd, mode_string(self), self->closefd ? "True" : "False");
}
else {
- res = PyUnicode_FromFormat("<_io.FileIO name=%R mode='%s'>",
- nameobj, mode_string(self));
+ res = PyUnicode_FromFormat(
+ "<_io.FileIO name=%R mode='%s' closefd=%s>",
+ nameobj, mode_string(self), self->closefd ? "True" : "False");
Py_DECREF(nameobj);
}
return res;
}
+/*[clinic input]
+_io.FileIO.isatty
+
+True if the file is connected to a TTY device.
+[clinic start generated code]*/
+
static PyObject *
-fileio_isatty(fileio *self)
+_io_FileIO_isatty_impl(fileio *self)
+/*[clinic end generated code: output=932c39924e9a8070 input=cd94ca1f5e95e843]*/
{
long res;
if (self->fd < 0)
return err_closed();
Py_BEGIN_ALLOW_THREADS
- res = isatty(self->fd);
+ _Py_BEGIN_SUPPRESS_IPH
+ if (_PyVerify_fd(self->fd))
+ res = isatty(self->fd);
+ else
+ res = 0;
+ _Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
return PyBool_FromLong(res);
}
@@ -1089,110 +1110,22 @@ fileio_getstate(fileio *self)
return NULL;
}
-
-PyDoc_STRVAR(fileio_doc,
-"file(name: str[, mode: str][, opener: None]) -> file IO object\n"
-"\n"
-"Open a file. The mode can be 'r' (default), 'w', 'x' or 'a' for reading,\n"
-"writing, exclusive creation or appending. The file will be created if it\n"
-"doesn't exist when opened for writing or appending; it will be truncated\n"
-"when opened for writing. A FileExistsError will be raised if it already\n"
-"exists when opened for creating. Opening a file for creating implies\n"
-"writing so this mode behaves in a similar way to 'w'.Add a '+' to the mode\n"
-"to allow simultaneous reading and writing. A custom opener can be used by\n"
-"passing a callable as *opener*. The underlying file descriptor for the file\n"
-"object is then obtained by calling opener with (*name*, *flags*).\n"
-"*opener* must return an open file descriptor (passing os.open as *opener*\n"
-"results in functionality similar to passing None).");
-
-PyDoc_STRVAR(read_doc,
-"read(size: int) -> bytes. read at most size bytes, returned as bytes.\n"
-"\n"
-"Only makes one system call, so less data may be returned than requested\n"
-"In non-blocking mode, returns None if no data is available.\n"
-"Return an empty bytes object at EOF.");
-
-PyDoc_STRVAR(readall_doc,
-"readall() -> bytes. read all data from the file, returned as bytes.\n"
-"\n"
-"In non-blocking mode, returns as much as is immediately available,\n"
-"or None if no data is available. Return an empty bytes object at EOF.");
-
-PyDoc_STRVAR(write_doc,
-"write(b: bytes) -> int. Write bytes b to file, return number written.\n"
-"\n"
-"Only makes one system call, so not all of the data may be written.\n"
-"The number of bytes actually written is returned. In non-blocking mode,\n"
-"returns None if the write would block."
-);
-
-PyDoc_STRVAR(fileno_doc,
-"fileno() -> int. Return the underlying file descriptor (an integer).");
-
-PyDoc_STRVAR(seek_doc,
-"seek(offset: int[, whence: int]) -> int. Move to new file position and\n"
-"return the file position.\n"
-"\n"
-"Argument offset is a byte count. Optional argument whence defaults to\n"
-"SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values\n"
-"are SEEK_CUR or 1 (move relative to current position, positive or negative),\n"
-"and SEEK_END or 2 (move relative to end of file, usually negative, although\n"
-"many platforms allow seeking beyond the end of a file).\n"
-"\n"
-"Note that not all file objects are seekable.");
-
-#ifdef HAVE_FTRUNCATE
-PyDoc_STRVAR(truncate_doc,
-"truncate([size: int]) -> int. Truncate the file to at most size bytes\n"
-"and return the truncated size.\n"
-"\n"
-"Size defaults to the current file position, as returned by tell().\n"
-"The current file position is changed to the value of size.");
-#endif
-
-PyDoc_STRVAR(tell_doc,
-"tell() -> int. Current file position.\n"
-"\n"
-"Can raise OSError for non seekable files."
-);
-
-PyDoc_STRVAR(readinto_doc,
-"readinto() -> Same as RawIOBase.readinto().");
-
-PyDoc_STRVAR(close_doc,
-"close() -> None. Close the file.\n"
-"\n"
-"A closed file cannot be used for further I/O operations. close() may be\n"
-"called more than once without error.");
-
-PyDoc_STRVAR(isatty_doc,
-"isatty() -> bool. True if the file is connected to a TTY device.");
-
-PyDoc_STRVAR(seekable_doc,
-"seekable() -> bool. True if file supports random-access.");
-
-PyDoc_STRVAR(readable_doc,
-"readable() -> bool. True if file was opened in a read mode.");
-
-PyDoc_STRVAR(writable_doc,
-"writable() -> bool. True if file was opened in a write mode.");
+#include "clinic/fileio.c.h"
static PyMethodDef fileio_methods[] = {
- {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc},
- {"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc},
- {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc},
- {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc},
- {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc},
- {"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc},
-#ifdef HAVE_FTRUNCATE
- {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc},
-#endif
- {"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc},
- {"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc},
- {"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc},
- {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc},
- {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc},
- {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc},
+ _IO_FILEIO_READ_METHODDEF
+ _IO_FILEIO_READALL_METHODDEF
+ _IO_FILEIO_READINTO_METHODDEF
+ _IO_FILEIO_WRITE_METHODDEF
+ _IO_FILEIO_SEEK_METHODDEF
+ _IO_FILEIO_TELL_METHODDEF
+ _IO_FILEIO_TRUNCATE_METHODDEF
+ _IO_FILEIO_CLOSE_METHODDEF
+ _IO_FILEIO_SEEKABLE_METHODDEF
+ _IO_FILEIO_READABLE_METHODDEF
+ _IO_FILEIO_WRITABLE_METHODDEF
+ _IO_FILEIO_FILENO_METHODDEF
+ _IO_FILEIO_ISATTY_METHODDEF
{"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL},
{"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL},
{NULL, NULL} /* sentinel */
@@ -1227,6 +1160,7 @@ static PyGetSetDef fileio_getsetlist[] = {
};
static PyMemberDef fileio_members[] = {
+ {"_blksize", T_UINT, offsetof(fileio, blksize), 0},
{"_finalizing", T_BOOL, offsetof(fileio, finalizing), 0},
{NULL}
};
@@ -1253,7 +1187,7 @@ PyTypeObject PyFileIO_Type = {
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
- fileio_doc, /* tp_doc */
+ _io_FileIO___init____doc__, /* tp_doc */
(traverseproc)fileio_traverse, /* tp_traverse */
(inquiry)fileio_clear, /* tp_clear */
0, /* tp_richcompare */
@@ -1268,7 +1202,7 @@ PyTypeObject PyFileIO_Type = {
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(fileio, dict), /* tp_dictoffset */
- fileio_init, /* tp_init */
+ _io_FileIO___init__, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
fileio_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index ef06b43ca6..025007e40d 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -13,6 +13,20 @@
#include "structmember.h"
#include "_iomodule.h"
+/*[clinic input]
+module _io
+class _io._IOBase "PyObject *" "&PyIOBase_Type"
+class _io._RawIOBase "PyObject *" "&PyRawIOBase_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d29a4d076c2b211c]*/
+
+/*[python input]
+class io_ssize_t_converter(CConverter):
+ type = 'Py_ssize_t'
+ converter = '_PyIO_ConvertSsize_t'
+[python start generated code]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/
+
/*
* IOBase class, an abstract class
*/
@@ -96,11 +110,15 @@ iobase_seek(PyObject *self, PyObject *args)
return iobase_unsupported("seek");
}
-PyDoc_STRVAR(iobase_tell_doc,
- "Return current stream position.");
+/*[clinic input]
+_io._IOBase.tell
+
+Return current stream position.
+[clinic start generated code]*/
static PyObject *
-iobase_tell(PyObject *self, PyObject *args)
+_io__IOBase_tell_impl(PyObject *self)
+/*[clinic end generated code: output=89a1c0807935abe2 input=04e615fec128801f]*/
{
_Py_IDENTIFIER(seek);
@@ -121,13 +139,17 @@ iobase_truncate(PyObject *self, PyObject *args)
/* Flush and close methods */
-PyDoc_STRVAR(iobase_flush_doc,
- "Flush write buffers, if applicable.\n"
- "\n"
- "This is not implemented for read-only and non-blocking streams.\n");
+/*[clinic input]
+_io._IOBase.flush
+
+Flush write buffers, if applicable.
+
+This is not implemented for read-only and non-blocking streams.
+[clinic start generated code]*/
static PyObject *
-iobase_flush(PyObject *self, PyObject *args)
+_io__IOBase_flush_impl(PyObject *self)
+/*[clinic end generated code: output=7cef4b4d54656a3b input=773be121abe270aa]*/
{
/* XXX Should this return the number of bytes written??? */
if (IS_CLOSED(self)) {
@@ -137,11 +159,6 @@ iobase_flush(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
-PyDoc_STRVAR(iobase_close_doc,
- "Flush and close the IO object.\n"
- "\n"
- "This method has no effect if the file is already closed.\n");
-
static int
iobase_closed(PyObject *self)
{
@@ -180,8 +197,17 @@ _PyIOBase_check_closed(PyObject *self, PyObject *args)
`__IOBase_closed` and call flush() by itself, but it is redundant with
whatever behaviour a non-trivial derived class will implement. */
+/*[clinic input]
+_io._IOBase.close
+
+Flush and close the IO object.
+
+This method has no effect if the file is already closed.
+[clinic start generated code]*/
+
static PyObject *
-iobase_close(PyObject *self, PyObject *args)
+_io__IOBase_close_impl(PyObject *self)
+/*[clinic end generated code: output=63c6a6f57d783d6d input=f4494d5c31dbc6b7]*/
{
PyObject *res;
@@ -304,14 +330,18 @@ iobase_dealloc(iobase *self)
/* Inquiry methods */
-PyDoc_STRVAR(iobase_seekable_doc,
- "Return whether object supports random access.\n"
- "\n"
- "If False, seek(), tell() and truncate() will raise UnsupportedOperation.\n"
- "This method may need to do a test seek().");
+/*[clinic input]
+_io._IOBase.seekable
+
+Return whether object supports random access.
+
+If False, seek(), tell() and truncate() will raise UnsupportedOperation.
+This method may need to do a test seek().
+[clinic start generated code]*/
static PyObject *
-iobase_seekable(PyObject *self, PyObject *args)
+_io__IOBase_seekable_impl(PyObject *self)
+/*[clinic end generated code: output=4c24c67f5f32a43d input=22676eebb81dcf1e]*/
{
Py_RETURN_FALSE;
}
@@ -333,13 +363,17 @@ _PyIOBase_check_seekable(PyObject *self, PyObject *args)
return res;
}
-PyDoc_STRVAR(iobase_readable_doc,
- "Return whether object was opened for reading.\n"
- "\n"
- "If False, read() will raise UnsupportedOperation.");
+/*[clinic input]
+_io._IOBase.readable
+
+Return whether object was opened for reading.
+
+If False, read() will raise UnsupportedOperation.
+[clinic start generated code]*/
static PyObject *
-iobase_readable(PyObject *self, PyObject *args)
+_io__IOBase_readable_impl(PyObject *self)
+/*[clinic end generated code: output=e48089250686388b input=12fc3d8f6be46434]*/
{
Py_RETURN_FALSE;
}
@@ -362,13 +396,17 @@ _PyIOBase_check_readable(PyObject *self, PyObject *args)
return res;
}
-PyDoc_STRVAR(iobase_writable_doc,
- "Return whether object was opened for writing.\n"
- "\n"
- "If False, write() will raise UnsupportedOperation.");
+/*[clinic input]
+_io._IOBase.writable
+
+Return whether object was opened for writing.
+
+If False, write() will raise UnsupportedOperation.
+[clinic start generated code]*/
static PyObject *
-iobase_writable(PyObject *self, PyObject *args)
+_io__IOBase_writable_impl(PyObject *self)
+/*[clinic end generated code: output=406001d0985be14f input=c17a0bb6a8dfc590]*/
{
Py_RETURN_FALSE;
}
@@ -413,24 +451,32 @@ iobase_exit(PyObject *self, PyObject *args)
/* XXX Should these be present even if unimplemented? */
-PyDoc_STRVAR(iobase_fileno_doc,
- "Returns underlying file descriptor if one exists.\n"
- "\n"
- "An IOError is raised if the IO object does not use a file descriptor.\n");
+/*[clinic input]
+_io._IOBase.fileno
+
+Returns underlying file descriptor if one exists.
+
+An IOError is raised if the IO object does not use a file descriptor.
+[clinic start generated code]*/
static PyObject *
-iobase_fileno(PyObject *self, PyObject *args)
+_io__IOBase_fileno_impl(PyObject *self)
+/*[clinic end generated code: output=7cc0973f0f5f3b73 input=32773c5df4b7eede]*/
{
return iobase_unsupported("fileno");
}
-PyDoc_STRVAR(iobase_isatty_doc,
- "Return whether this is an 'interactive' stream.\n"
- "\n"
- "Return False if it can't be determined.\n");
+/*[clinic input]
+_io._IOBase.isatty
+
+Return whether this is an 'interactive' stream.
+
+Return False if it can't be determined.
+[clinic start generated code]*/
static PyObject *
-iobase_isatty(PyObject *self, PyObject *args)
+_io__IOBase_isatty_impl(PyObject *self)
+/*[clinic end generated code: output=60cab77cede41cdd input=9ef76530d368458b]*/
{
if (_PyIOBase_check_closed(self, Py_True) == NULL)
return NULL;
@@ -439,30 +485,31 @@ iobase_isatty(PyObject *self, PyObject *args)
/* Readline(s) and writelines */
-PyDoc_STRVAR(iobase_readline_doc,
- "Read and return a line from the stream.\n"
- "\n"
- "If limit is specified, at most limit bytes will be read.\n"
- "\n"
- "The line terminator is always b'\\n' for binary files; for text\n"
- "files, the newlines argument to open can be used to select the line\n"
- "terminator(s) recognized.\n");
+/*[clinic input]
+_io._IOBase.readline
+ size as limit: io_ssize_t = -1
+ /
+
+Read and return a line from the stream.
+
+If size is specified, at most size bytes will be read.
+
+The line terminator is always b'\n' for binary files; for text
+files, the newlines argument to open can be used to select the line
+terminator(s) recognized.
+[clinic start generated code]*/
static PyObject *
-iobase_readline(PyObject *self, PyObject *args)
+_io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit)
+/*[clinic end generated code: output=4479f79b58187840 input=df4cc8884f553cab]*/
{
/* For backwards compatibility, a (slowish) readline(). */
- Py_ssize_t limit = -1;
int has_peek = 0;
PyObject *buffer, *result;
Py_ssize_t old_size = -1;
_Py_IDENTIFIER(peek);
- if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit)) {
- return NULL;
- }
-
if (_PyObject_HasAttrId(self, &PyId_peek))
has_peek = 1;
@@ -585,23 +632,25 @@ iobase_iternext(PyObject *self)
return line;
}
-PyDoc_STRVAR(iobase_readlines_doc,
- "Return a list of lines from the stream.\n"
- "\n"
- "hint can be specified to control the number of lines read: no more\n"
- "lines will be read if the total size (in bytes/characters) of all\n"
- "lines so far exceeds hint.");
+/*[clinic input]
+_io._IOBase.readlines
+ hint: io_ssize_t = -1
+ /
+
+Return a list of lines from the stream.
+
+hint can be specified to control the number of lines read: no more
+lines will be read if the total size (in bytes/characters) of all
+lines so far exceeds hint.
+[clinic start generated code]*/
static PyObject *
-iobase_readlines(PyObject *self, PyObject *args)
+_io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint)
+/*[clinic end generated code: output=2f50421677fa3dea input=1961c4a95e96e661]*/
{
- Py_ssize_t hint = -1, length = 0;
+ Py_ssize_t length = 0;
PyObject *result;
- if (!PyArg_ParseTuple(args, "|O&:readlines", &_PyIO_ConvertSsize_t, &hint)) {
- return NULL;
- }
-
result = PyList_New(0);
if (result == NULL)
return NULL;
@@ -646,14 +695,17 @@ iobase_readlines(PyObject *self, PyObject *args)
return result;
}
+/*[clinic input]
+_io._IOBase.writelines
+ lines: object
+ /
+[clinic start generated code]*/
+
static PyObject *
-iobase_writelines(PyObject *self, PyObject *args)
+_io__IOBase_writelines(PyObject *self, PyObject *lines)
+/*[clinic end generated code: output=976eb0a9b60a6628 input=432e729a8450b3cb]*/
{
- PyObject *lines, *iter, *res;
-
- if (!PyArg_ParseTuple(args, "O:writelines", &lines)) {
- return NULL;
- }
+ PyObject *iter, *res;
if (_PyIOBase_check_closed(self, Py_True) == NULL)
return NULL;
@@ -688,31 +740,33 @@ iobase_writelines(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
+#include "clinic/iobase.c.h"
+
static PyMethodDef iobase_methods[] = {
{"seek", iobase_seek, METH_VARARGS, iobase_seek_doc},
- {"tell", iobase_tell, METH_NOARGS, iobase_tell_doc},
+ _IO__IOBASE_TELL_METHODDEF
{"truncate", iobase_truncate, METH_VARARGS, iobase_truncate_doc},
- {"flush", iobase_flush, METH_NOARGS, iobase_flush_doc},
- {"close", iobase_close, METH_NOARGS, iobase_close_doc},
+ _IO__IOBASE_FLUSH_METHODDEF
+ _IO__IOBASE_CLOSE_METHODDEF
- {"seekable", iobase_seekable, METH_NOARGS, iobase_seekable_doc},
- {"readable", iobase_readable, METH_NOARGS, iobase_readable_doc},
- {"writable", iobase_writable, METH_NOARGS, iobase_writable_doc},
+ _IO__IOBASE_SEEKABLE_METHODDEF
+ _IO__IOBASE_READABLE_METHODDEF
+ _IO__IOBASE_WRITABLE_METHODDEF
{"_checkClosed", _PyIOBase_check_closed, METH_NOARGS},
{"_checkSeekable", _PyIOBase_check_seekable, METH_NOARGS},
{"_checkReadable", _PyIOBase_check_readable, METH_NOARGS},
{"_checkWritable", _PyIOBase_check_writable, METH_NOARGS},
- {"fileno", iobase_fileno, METH_NOARGS, iobase_fileno_doc},
- {"isatty", iobase_isatty, METH_NOARGS, iobase_isatty_doc},
+ _IO__IOBASE_FILENO_METHODDEF
+ _IO__IOBASE_ISATTY_METHODDEF
{"__enter__", iobase_enter, METH_NOARGS},
{"__exit__", iobase_exit, METH_VARARGS},
- {"readline", iobase_readline, METH_VARARGS, iobase_readline_doc},
- {"readlines", iobase_readlines, METH_VARARGS, iobase_readlines_doc},
- {"writelines", iobase_writelines, METH_VARARGS},
+ _IO__IOBASE_READLINE_METHODDEF
+ _IO__IOBASE_READLINES_METHODDEF
+ _IO__IOBASE_WRITELINES_METHODDEF
{NULL, NULL}
};
@@ -795,16 +849,18 @@ PyDoc_STRVAR(rawiobase_doc,
* either.)
*/
+/*[clinic input]
+_io._RawIOBase.read
+ size as n: Py_ssize_t = -1
+ /
+[clinic start generated code]*/
+
static PyObject *
-rawiobase_read(PyObject *self, PyObject *args)
+_io__RawIOBase_read_impl(PyObject *self, Py_ssize_t n)
+/*[clinic end generated code: output=6cdeb731e3c9f13c input=b6d0dcf6417d1374]*/
{
- Py_ssize_t n = -1;
PyObject *b, *res;
- if (!PyArg_ParseTuple(args, "|n:read", &n)) {
- return NULL;
- }
-
if (n < 0) {
_Py_IDENTIFIER(readall);
@@ -836,11 +892,15 @@ rawiobase_read(PyObject *self, PyObject *args)
}
-PyDoc_STRVAR(rawiobase_readall_doc,
- "Read until EOF, using multiple read() call.");
+/*[clinic input]
+_io._RawIOBase.readall
+
+Read until EOF, using multiple read() call.
+[clinic start generated code]*/
static PyObject *
-rawiobase_readall(PyObject *self, PyObject *args)
+_io__RawIOBase_readall_impl(PyObject *self)
+/*[clinic end generated code: output=1987b9ce929425a0 input=688874141213622a]*/
{
int r;
PyObject *chunks = PyList_New(0);
@@ -892,9 +952,25 @@ rawiobase_readall(PyObject *self, PyObject *args)
return result;
}
+static PyObject *
+rawiobase_readinto(PyObject *self, PyObject *args)
+{
+ PyErr_SetNone(PyExc_NotImplementedError);
+ return NULL;
+}
+
+static PyObject *
+rawiobase_write(PyObject *self, PyObject *args)
+{
+ PyErr_SetNone(PyExc_NotImplementedError);
+ return NULL;
+}
+
static PyMethodDef rawiobase_methods[] = {
- {"read", rawiobase_read, METH_VARARGS},
- {"readall", rawiobase_readall, METH_NOARGS, rawiobase_readall_doc},
+ _IO__RAWIOBASE_READ_METHODDEF
+ _IO__RAWIOBASE_READALL_METHODDEF
+ {"readinto", rawiobase_readinto, METH_VARARGS},
+ {"write", rawiobase_write, METH_VARARGS},
{NULL, NULL}
};
diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c
index 9d73884f73..8315ab8e70 100644
--- a/Modules/_io/stringio.c
+++ b/Modules/_io/stringio.c
@@ -11,6 +11,12 @@
#define STATE_REALIZED 1
#define STATE_ACCUMULATING 2
+/*[clinic input]
+module _io
+class _io.StringIO "stringio *" "&PyStringIO_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c17bc0f42165cd7d]*/
+
typedef struct {
PyObject_HEAD
Py_UCS4 *buf;
@@ -39,6 +45,8 @@ typedef struct {
PyObject *weakreflist;
} stringio;
+static int _io_StringIO___init__(PyObject *self, PyObject *args, PyObject *kwargs);
+
#define CHECK_INITIALIZED(self) \
if (self->ok <= 0) { \
PyErr_SetString(PyExc_ValueError, \
@@ -58,12 +66,6 @@ typedef struct {
return NULL; \
}
-PyDoc_STRVAR(stringio_doc,
- "Text I/O implementation using an in-memory buffer.\n"
- "\n"
- "The initial_value argument sets the value of object. The newline\n"
- "argument is like the one of TextIOWrapper's constructor.");
-
/* Internal routine for changing the size, in terms of characters, of the
buffer of StringIO objects. The caller should ensure that the 'size'
@@ -264,11 +266,15 @@ fail:
return -1;
}
-PyDoc_STRVAR(stringio_getvalue_doc,
- "Retrieve the entire contents of the object.");
+/*[clinic input]
+_io.StringIO.getvalue
+
+Retrieve the entire contents of the object.
+[clinic start generated code]*/
static PyObject *
-stringio_getvalue(stringio *self)
+_io_StringIO_getvalue_impl(stringio *self)
+/*[clinic end generated code: output=27b6a7bfeaebce01 input=d23cb81d6791cf88]*/
{
CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
@@ -278,33 +284,40 @@ stringio_getvalue(stringio *self)
self->string_size);
}
-PyDoc_STRVAR(stringio_tell_doc,
- "Tell the current file position.");
+/*[clinic input]
+_io.StringIO.tell
+
+Tell the current file position.
+[clinic start generated code]*/
static PyObject *
-stringio_tell(stringio *self)
+_io_StringIO_tell_impl(stringio *self)
+/*[clinic end generated code: output=2e87ac67b116c77b input=ec866ebaff02f405]*/
{
CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
return PyLong_FromSsize_t(self->pos);
}
-PyDoc_STRVAR(stringio_read_doc,
- "Read at most n characters, returned as a string.\n"
- "\n"
- "If the argument is negative or omitted, read until EOF\n"
- "is reached. Return an empty string at EOF.\n");
+/*[clinic input]
+_io.StringIO.read
+ size as arg: object = None
+ /
+
+Read at most size characters, returned as a string.
+
+If the argument is negative or omitted, read until EOF
+is reached. Return an empty string at EOF.
+[clinic start generated code]*/
static PyObject *
-stringio_read(stringio *self, PyObject *args)
+_io_StringIO_read_impl(stringio *self, PyObject *arg)
+/*[clinic end generated code: output=3676864773746f68 input=9a319015f6f3965c]*/
{
Py_ssize_t size, n;
Py_UCS4 *output;
- PyObject *arg = Py_None;
CHECK_INITIALIZED(self);
- if (!PyArg_ParseTuple(args, "|O:read", &arg))
- return NULL;
CHECK_CLOSED(self);
if (PyNumber_Check(arg)) {
@@ -373,20 +386,23 @@ _stringio_readline(stringio *self, Py_ssize_t limit)
return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, start, len);
}
-PyDoc_STRVAR(stringio_readline_doc,
- "Read until newline or EOF.\n"
- "\n"
- "Returns an empty string if EOF is hit immediately.\n");
+/*[clinic input]
+_io.StringIO.readline
+ size as arg: object = None
+ /
+
+Read until newline or EOF.
+
+Returns an empty string if EOF is hit immediately.
+[clinic start generated code]*/
static PyObject *
-stringio_readline(stringio *self, PyObject *args)
+_io_StringIO_readline_impl(stringio *self, PyObject *arg)
+/*[clinic end generated code: output=99fdcac03a3dee81 input=e0e0ed4042040176]*/
{
- PyObject *arg = Py_None;
Py_ssize_t limit = -1;
CHECK_INITIALIZED(self);
- if (!PyArg_ParseTuple(args, "|O:readline", &arg))
- return NULL;
CHECK_CLOSED(self);
ENSURE_REALIZED(self);
@@ -441,22 +457,25 @@ stringio_iternext(stringio *self)
return line;
}
-PyDoc_STRVAR(stringio_truncate_doc,
- "Truncate size to pos.\n"
- "\n"
- "The pos argument defaults to the current file position, as\n"
- "returned by tell(). The current file position is unchanged.\n"
- "Returns the new absolute position.\n");
+/*[clinic input]
+_io.StringIO.truncate
+ pos as arg: object = None
+ /
+
+Truncate size to pos.
+
+The pos argument defaults to the current file position, as
+returned by tell(). The current file position is unchanged.
+Returns the new absolute position.
+[clinic start generated code]*/
static PyObject *
-stringio_truncate(stringio *self, PyObject *args)
+_io_StringIO_truncate_impl(stringio *self, PyObject *arg)
+/*[clinic end generated code: output=6072439c2b01d306 input=748619a494ba53ad]*/
{
Py_ssize_t size;
- PyObject *arg = Py_None;
CHECK_INITIALIZED(self);
- if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
- return NULL;
CHECK_CLOSED(self);
if (PyNumber_Check(arg)) {
@@ -490,49 +509,51 @@ stringio_truncate(stringio *self, PyObject *args)
return PyLong_FromSsize_t(size);
}
-PyDoc_STRVAR(stringio_seek_doc,
- "Change stream position.\n"
- "\n"
- "Seek to character offset pos relative to position indicated by whence:\n"
- " 0 Start of stream (the default). pos should be >= 0;\n"
- " 1 Current position - pos must be 0;\n"
- " 2 End of stream - pos must be 0.\n"
- "Returns the new absolute position.\n");
+/*[clinic input]
+_io.StringIO.seek
+ pos: Py_ssize_t
+ whence: int = 0
+ /
+
+Change stream position.
+
+Seek to character offset pos relative to position indicated by whence:
+ 0 Start of stream (the default). pos should be >= 0;
+ 1 Current position - pos must be 0;
+ 2 End of stream - pos must be 0.
+Returns the new absolute position.
+[clinic start generated code]*/
static PyObject *
-stringio_seek(stringio *self, PyObject *args)
+_io_StringIO_seek_impl(stringio *self, Py_ssize_t pos, int whence)
+/*[clinic end generated code: output=e9e0ac9a8ae71c25 input=e3855b24e7cae06a]*/
{
- Py_ssize_t pos;
- int mode = 0;
-
CHECK_INITIALIZED(self);
- if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode))
- return NULL;
CHECK_CLOSED(self);
- if (mode != 0 && mode != 1 && mode != 2) {
+ if (whence != 0 && whence != 1 && whence != 2) {
PyErr_Format(PyExc_ValueError,
- "Invalid whence (%i, should be 0, 1 or 2)", mode);
+ "Invalid whence (%i, should be 0, 1 or 2)", whence);
return NULL;
}
- else if (pos < 0 && mode == 0) {
+ else if (pos < 0 && whence == 0) {
PyErr_Format(PyExc_ValueError,
"Negative seek position %zd", pos);
return NULL;
}
- else if (mode != 0 && pos != 0) {
+ else if (whence != 0 && pos != 0) {
PyErr_SetString(PyExc_IOError,
"Can't do nonzero cur-relative seeks");
return NULL;
}
- /* mode 0: offset relative to beginning of the string.
- mode 1: no change to current position.
- mode 2: change position to end of file. */
- if (mode == 1) {
+ /* whence = 0: offset relative to beginning of the string.
+ whence = 1: no change to current position.
+ whence = 2: change position to end of file. */
+ if (whence == 1) {
pos = self->pos;
}
- else if (mode == 2) {
+ else if (whence == 2) {
pos = self->string_size;
}
@@ -541,14 +562,20 @@ stringio_seek(stringio *self, PyObject *args)
return PyLong_FromSsize_t(self->pos);
}
-PyDoc_STRVAR(stringio_write_doc,
- "Write string to file.\n"
- "\n"
- "Returns the number of characters written, which is always equal to\n"
- "the length of the string.\n");
+/*[clinic input]
+_io.StringIO.write
+ s as obj: object
+ /
+
+Write string to file.
+
+Returns the number of characters written, which is always equal to
+the length of the string.
+[clinic start generated code]*/
static PyObject *
-stringio_write(stringio *self, PyObject *obj)
+_io_StringIO_write(stringio *self, PyObject *obj)
+/*[clinic end generated code: output=0deaba91a15b94da input=cf96f3b16586e669]*/
{
Py_ssize_t size;
@@ -569,14 +596,20 @@ stringio_write(stringio *self, PyObject *obj)
return PyLong_FromSsize_t(size);
}
-PyDoc_STRVAR(stringio_close_doc,
- "Close the IO object. Attempting any further operation after the\n"
- "object is closed will raise a ValueError.\n"
- "\n"
- "This method has no effect if the file is already closed.\n");
+/*[clinic input]
+_io.StringIO.close
+
+Close the IO object.
+
+Attempting any further operation after the object is closed
+will raise a ValueError.
+
+This method has no effect if the file is already closed.
+[clinic start generated code]*/
static PyObject *
-stringio_close(stringio *self)
+_io_StringIO_close_impl(stringio *self)
+/*[clinic end generated code: output=04399355cbe518f1 input=cbc10b45f35d6d46]*/
{
self->closed = 1;
/* Free up some memory */
@@ -644,19 +677,25 @@ stringio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject *)self;
}
+/*[clinic input]
+_io.StringIO.__init__
+ initial_value as value: object(c_default="NULL") = ''
+ newline as newline_obj: object(c_default="NULL") = '\n'
+
+Text I/O implementation using an in-memory buffer.
+
+The initial_value argument sets the value of object. The newline
+argument is like the one of TextIOWrapper's constructor.
+[clinic start generated code]*/
+
static int
-stringio_init(stringio *self, PyObject *args, PyObject *kwds)
+_io_StringIO___init___impl(stringio *self, PyObject *value,
+ PyObject *newline_obj)
+/*[clinic end generated code: output=a421ea023b22ef4e input=cee2d9181b2577a3]*/
{
- char *kwlist[] = {"initial_value", "newline", NULL};
- PyObject *value = NULL;
- PyObject *newline_obj = NULL;
char *newline = "\n";
Py_ssize_t value_len;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:__init__", kwlist,
- &value, &newline_obj))
- return -1;
-
/* Parse the newline argument. This used to be done with the 'z'
specifier, however this allowed any object with the buffer interface to
be converted. Thus we have to parse it manually since we only want to
@@ -761,33 +800,45 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds)
/* Properties and pseudo-properties */
-PyDoc_STRVAR(stringio_readable_doc,
-"readable() -> bool. Returns True if the IO object can be read.");
+/*[clinic input]
+_io.StringIO.readable
-PyDoc_STRVAR(stringio_writable_doc,
-"writable() -> bool. Returns True if the IO object can be written.");
-
-PyDoc_STRVAR(stringio_seekable_doc,
-"seekable() -> bool. Returns True if the IO object can be seeked.");
+Returns True if the IO object can be read.
+[clinic start generated code]*/
static PyObject *
-stringio_seekable(stringio *self, PyObject *args)
+_io_StringIO_readable_impl(stringio *self)
+/*[clinic end generated code: output=b19d44dd8b1ceb99 input=39ce068b224c21ad]*/
{
CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
Py_RETURN_TRUE;
}
+/*[clinic input]
+_io.StringIO.writable
+
+Returns True if the IO object can be written.
+[clinic start generated code]*/
+
static PyObject *
-stringio_readable(stringio *self, PyObject *args)
+_io_StringIO_writable_impl(stringio *self)
+/*[clinic end generated code: output=13e4dd77187074ca input=7a691353aac38835]*/
{
CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
Py_RETURN_TRUE;
}
+/*[clinic input]
+_io.StringIO.seekable
+
+Returns True if the IO object can be seeked.
+[clinic start generated code]*/
+
static PyObject *
-stringio_writable(stringio *self, PyObject *args)
+_io_StringIO_seekable_impl(stringio *self)
+/*[clinic end generated code: output=4d20b4641c756879 input=4c606d05b32952e6]*/
{
CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
@@ -809,7 +860,7 @@ stringio_writable(stringio *self, PyObject *args)
static PyObject *
stringio_getstate(stringio *self)
{
- PyObject *initvalue = stringio_getvalue(self);
+ PyObject *initvalue = _io_StringIO_getvalue_impl(self);
PyObject *dict;
PyObject *state;
@@ -857,7 +908,7 @@ stringio_setstate(stringio *self, PyObject *state)
initarg = PyTuple_GetSlice(state, 0, 2);
if (initarg == NULL)
return NULL;
- if (stringio_init(self, initarg, NULL) < 0) {
+ if (_io_StringIO___init__((PyObject *)self, initarg, NULL) < 0) {
Py_DECREF(initarg);
return NULL;
}
@@ -959,19 +1010,21 @@ stringio_newlines(stringio *self, void *context)
return PyObject_GetAttr(self->decoder, _PyIO_str_newlines);
}
+#include "clinic/stringio.c.h"
+
static struct PyMethodDef stringio_methods[] = {
- {"close", (PyCFunction)stringio_close, METH_NOARGS, stringio_close_doc},
- {"getvalue", (PyCFunction)stringio_getvalue, METH_NOARGS, stringio_getvalue_doc},
- {"read", (PyCFunction)stringio_read, METH_VARARGS, stringio_read_doc},
- {"readline", (PyCFunction)stringio_readline, METH_VARARGS, stringio_readline_doc},
- {"tell", (PyCFunction)stringio_tell, METH_NOARGS, stringio_tell_doc},
- {"truncate", (PyCFunction)stringio_truncate, METH_VARARGS, stringio_truncate_doc},
- {"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc},
- {"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc},
-
- {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS, stringio_seekable_doc},
- {"readable", (PyCFunction)stringio_readable, METH_NOARGS, stringio_readable_doc},
- {"writable", (PyCFunction)stringio_writable, METH_NOARGS, stringio_writable_doc},
+ _IO_STRINGIO_CLOSE_METHODDEF
+ _IO_STRINGIO_GETVALUE_METHODDEF
+ _IO_STRINGIO_READ_METHODDEF
+ _IO_STRINGIO_READLINE_METHODDEF
+ _IO_STRINGIO_TELL_METHODDEF
+ _IO_STRINGIO_TRUNCATE_METHODDEF
+ _IO_STRINGIO_SEEK_METHODDEF
+ _IO_STRINGIO_WRITE_METHODDEF
+
+ _IO_STRINGIO_SEEKABLE_METHODDEF
+ _IO_STRINGIO_READABLE_METHODDEF
+ _IO_STRINGIO_WRITABLE_METHODDEF
{"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS},
{"__setstate__", (PyCFunction)stringio_setstate, METH_O},
@@ -1013,7 +1066,7 @@ PyTypeObject PyStringIO_Type = {
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC, /*tp_flags*/
- stringio_doc, /*tp_doc*/
+ _io_StringIO___init____doc__, /*tp_doc*/
(traverseproc)stringio_traverse, /*tp_traverse*/
(inquiry)stringio_clear, /*tp_clear*/
0, /*tp_richcompare*/
@@ -1028,7 +1081,7 @@ PyTypeObject PyStringIO_Type = {
0, /*tp_descr_get*/
0, /*tp_descr_set*/
offsetof(stringio, dict), /*tp_dictoffset*/
- (initproc)stringio_init, /*tp_init*/
+ _io_StringIO___init__, /*tp_init*/
0, /*tp_alloc*/
stringio_new, /*tp_new*/
};
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index b419275a80..c962c0ba08 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -11,6 +11,20 @@
#include "structmember.h"
#include "_iomodule.h"
+/*[clinic input]
+module _io
+class _io.IncrementalNewlineDecoder "nldecoder_object *" "&PyIncrementalNewlineDecoder_Type"
+class _io.TextIOWrapper "textio *" "&TextIOWrapper_TYpe"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2097a4fc85670c26]*/
+
+/*[python input]
+class io_ssize_t_converter(CConverter):
+ type = 'Py_ssize_t'
+ converter = '_PyIO_ConvertSsize_t'
+[python start generated code]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/
+
_Py_IDENTIFIER(close);
_Py_IDENTIFIER(_dealloc_warn);
_Py_IDENTIFIER(decode);
@@ -210,38 +224,37 @@ PyTypeObject PyTextIOBase_Type = {
/* IncrementalNewlineDecoder */
-PyDoc_STRVAR(incrementalnewlinedecoder_doc,
- "Codec used when reading a file in universal newlines mode. It wraps\n"
- "another incremental decoder, translating \\r\\n and \\r into \\n. It also\n"
- "records the types of newlines encountered. When used with\n"
- "translate=False, it ensures that the newline sequence is returned in\n"
- "one piece. When used with decoder=None, it expects unicode strings as\n"
- "decode input and translates newlines without first invoking an external\n"
- "decoder.\n"
- );
-
typedef struct {
PyObject_HEAD
PyObject *decoder;
PyObject *errors;
- signed int pendingcr: 1;
- signed int translate: 1;
+ unsigned int pendingcr: 1;
+ unsigned int translate: 1;
unsigned int seennl: 3;
} nldecoder_object;
-static int
-incrementalnewlinedecoder_init(nldecoder_object *self,
- PyObject *args, PyObject *kwds)
-{
- PyObject *decoder;
- int translate;
- PyObject *errors = NULL;
- char *kwlist[] = {"decoder", "translate", "errors", NULL};
+/*[clinic input]
+_io.IncrementalNewlineDecoder.__init__
+ decoder: object
+ translate: int
+ errors: object(c_default="NULL") = "strict"
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi|O:IncrementalNewlineDecoder",
- kwlist, &decoder, &translate, &errors))
- return -1;
+Codec used when reading a file in universal newlines mode.
+
+It wraps another incremental decoder, translating \r\n and \r into \n.
+It also records the types of newlines encountered. When used with
+translate=False, it ensures that the newline sequence is returned in
+one piece. When used with decoder=None, it expects unicode strings as
+decode input and translates newlines without first invoking an external
+decoder.
+[clinic start generated code]*/
+static int
+_io_IncrementalNewlineDecoder___init___impl(nldecoder_object *self,
+ PyObject *decoder, int translate,
+ PyObject *errors)
+/*[clinic end generated code: output=fbd04d443e764ec2 input=89db6b19c6b126bf]*/
+{
self->decoder = decoder;
Py_INCREF(decoder);
@@ -495,22 +508,27 @@ _PyIncrementalNewlineDecoder_decode(PyObject *myself,
return NULL;
}
+/*[clinic input]
+_io.IncrementalNewlineDecoder.decode
+ input: object
+ final: int(c_default="0") = False
+[clinic start generated code]*/
+
static PyObject *
-incrementalnewlinedecoder_decode(nldecoder_object *self,
- PyObject *args, PyObject *kwds)
+_io_IncrementalNewlineDecoder_decode_impl(nldecoder_object *self,
+ PyObject *input, int final)
+/*[clinic end generated code: output=0d486755bb37a66e input=d65677385bfd6827]*/
{
- char *kwlist[] = {"input", "final", NULL};
- PyObject *input;
- int final = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:IncrementalNewlineDecoder",
- kwlist, &input, &final))
- return NULL;
return _PyIncrementalNewlineDecoder_decode((PyObject *) self, input, final);
}
+/*[clinic input]
+_io.IncrementalNewlineDecoder.getstate
+[clinic start generated code]*/
+
static PyObject *
-incrementalnewlinedecoder_getstate(nldecoder_object *self, PyObject *args)
+_io_IncrementalNewlineDecoder_getstate_impl(nldecoder_object *self)
+/*[clinic end generated code: output=f0d2c9c136f4e0d0 input=f8ff101825e32e7f]*/
{
PyObject *buffer;
unsigned PY_LONG_LONG flag;
@@ -520,7 +538,7 @@ incrementalnewlinedecoder_getstate(nldecoder_object *self, PyObject *args)
_PyIO_str_getstate, NULL);
if (state == NULL)
return NULL;
- if (!PyArg_Parse(state, "(OK)", &buffer, &flag)) {
+ if (!PyArg_ParseTuple(state, "OK", &buffer, &flag)) {
Py_DECREF(state);
return NULL;
}
@@ -537,16 +555,24 @@ incrementalnewlinedecoder_getstate(nldecoder_object *self, PyObject *args)
return Py_BuildValue("NK", buffer, flag);
}
+/*[clinic input]
+_io.IncrementalNewlineDecoder.setstate
+ state: object
+ /
+[clinic start generated code]*/
+
static PyObject *
-incrementalnewlinedecoder_setstate(nldecoder_object *self, PyObject *state)
+_io_IncrementalNewlineDecoder_setstate(nldecoder_object *self,
+ PyObject *state)
+/*[clinic end generated code: output=c10c622508b576cb input=c53fb505a76dbbe2]*/
{
PyObject *buffer;
unsigned PY_LONG_LONG flag;
- if (!PyArg_Parse(state, "(OK)", &buffer, &flag))
+ if (!PyArg_ParseTuple(state, "OK", &buffer, &flag))
return NULL;
- self->pendingcr = (int) flag & 1;
+ self->pendingcr = (int) (flag & 1);
flag >>= 1;
if (self->decoder != Py_None)
@@ -556,8 +582,13 @@ incrementalnewlinedecoder_setstate(nldecoder_object *self, PyObject *state)
Py_RETURN_NONE;
}
+/*[clinic input]
+_io.IncrementalNewlineDecoder.reset
+[clinic start generated code]*/
+
static PyObject *
-incrementalnewlinedecoder_reset(nldecoder_object *self, PyObject *args)
+_io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self)
+/*[clinic end generated code: output=32fa40c7462aa8ff input=728678ddaea776df]*/
{
self->seennl = 0;
self->pendingcr = 0;
@@ -591,95 +622,8 @@ incrementalnewlinedecoder_newlines_get(nldecoder_object *self, void *context)
}
-
-static PyMethodDef incrementalnewlinedecoder_methods[] = {
- {"decode", (PyCFunction)incrementalnewlinedecoder_decode, METH_VARARGS|METH_KEYWORDS},
- {"getstate", (PyCFunction)incrementalnewlinedecoder_getstate, METH_NOARGS},
- {"setstate", (PyCFunction)incrementalnewlinedecoder_setstate, METH_O},
- {"reset", (PyCFunction)incrementalnewlinedecoder_reset, METH_NOARGS},
- {NULL}
-};
-
-static PyGetSetDef incrementalnewlinedecoder_getset[] = {
- {"newlines", (getter)incrementalnewlinedecoder_newlines_get, NULL, NULL},
- {NULL}
-};
-
-PyTypeObject PyIncrementalNewlineDecoder_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io.IncrementalNewlineDecoder", /*tp_name*/
- sizeof(nldecoder_object), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)incrementalnewlinedecoder_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare */
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
- incrementalnewlinedecoder_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /*tp_weaklistoffset*/
- 0, /* tp_iter */
- 0, /* tp_iternext */
- incrementalnewlinedecoder_methods, /* tp_methods */
- 0, /* tp_members */
- incrementalnewlinedecoder_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)incrementalnewlinedecoder_init, /* tp_init */
- 0, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
-};
-
-
/* TextIOWrapper */
-PyDoc_STRVAR(textiowrapper_doc,
- "Character and line based layer over a BufferedIOBase object, buffer.\n"
- "\n"
- "encoding gives the name of the encoding that the stream will be\n"
- "decoded or encoded with. It defaults to locale.getpreferredencoding(False).\n"
- "\n"
- "errors determines the strictness of encoding and decoding (see\n"
- "help(codecs.Codec) or the documentation for codecs.register) and\n"
- "defaults to \"strict\".\n"
- "\n"
- "newline controls how line endings are handled. It can be None, '',\n"
- "'\\n', '\\r', and '\\r\\n'. It works as 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 line_buffering is True, a call to flush is implied when a call to\n"
- "write contains a newline character."
- );
-
typedef PyObject *
(*encodefunc_t)(PyObject *, PyObject *);
@@ -742,7 +686,6 @@ typedef struct
PyObject *dict;
} textio;
-
/* A couple of specialized cases in order to bypass the slow incremental
encoding methods for the most popular encodings. */
@@ -843,28 +786,59 @@ static encodefuncentry encodefuncs[] = {
};
+/*[clinic input]
+_io.TextIOWrapper.__init__
+ buffer: object
+ encoding: str(accept={str, NoneType}) = NULL
+ errors: str(accept={str, NoneType}) = NULL
+ newline: str(accept={str, NoneType}) = NULL
+ line_buffering: int(c_default="0") = False
+ write_through: int(c_default="0") = False
+
+Character and line based layer over a BufferedIOBase object, buffer.
+
+encoding gives the name of the encoding that the stream will be
+decoded or encoded with. It defaults to locale.getpreferredencoding(False).
+
+errors determines the strictness of encoding and decoding (see
+help(codecs.Codec) or the documentation for codecs.register) and
+defaults to "strict".
+
+newline controls how line endings are handled. 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 line_buffering is True, a call to flush is implied when a call to
+write contains a newline character.
+[clinic start generated code]*/
+
static int
-textiowrapper_init(textio *self, PyObject *args, PyObject *kwds)
-{
- char *kwlist[] = {"buffer", "encoding", "errors",
- "newline", "line_buffering", "write_through",
- NULL};
- PyObject *buffer, *raw, *codec_info = NULL;
- char *encoding = NULL;
- char *errors = NULL;
- char *newline = NULL;
- int line_buffering = 0, write_through = 0;
+_io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
+ const char *encoding, const char *errors,
+ const char *newline, int line_buffering,
+ int write_through)
+/*[clinic end generated code: output=56a83402ce2a8381 input=3126cb3101a2c99b]*/
+{
+ PyObject *raw, *codec_info = NULL;
_PyIO_State *state = NULL;
-
PyObject *res;
int r;
self->ok = 0;
self->detached = 0;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|zzzii:fileio",
- kwlist, &buffer, &encoding, &errors,
- &newline, &line_buffering, &write_through))
- return -1;
if (newline && newline[0] != '\0'
&& !(newline[0] == '\n' && newline[1] == '\0')
@@ -1244,8 +1218,13 @@ textiowrapper_closed_get(textio *self, void *context);
}
+/*[clinic input]
+_io.TextIOWrapper.detach
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_detach(textio *self)
+_io_TextIOWrapper_detach_impl(textio *self)
+/*[clinic end generated code: output=7ba3715cd032d5f2 input=e5a71fbda9e1d9f9]*/
{
PyObject *buffer, *res;
CHECK_ATTACHED(self);
@@ -1290,25 +1269,26 @@ _textiowrapper_writeflush(textio *self)
return 0;
}
+/*[clinic input]
+_io.TextIOWrapper.write
+ text: unicode
+ /
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_write(textio *self, PyObject *args)
+_io_TextIOWrapper_write_impl(textio *self, PyObject *text)
+/*[clinic end generated code: output=d2deb0d50771fcec input=fdf19153584a0e44]*/
{
PyObject *ret;
- PyObject *text; /* owned reference */
PyObject *b;
Py_ssize_t textlen;
int haslf = 0;
int needflush = 0, text_needflush = 0;
- CHECK_ATTACHED(self);
-
- if (!PyArg_ParseTuple(args, "U:write", &text)) {
- return NULL;
- }
-
if (PyUnicode_READY(text) == -1)
return NULL;
+ CHECK_ATTACHED(self);
CHECK_CLOSED(self);
if (self->encoder == NULL)
@@ -1441,6 +1421,7 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint)
PyObject *dec_buffer = NULL;
PyObject *dec_flags = NULL;
PyObject *input_chunk = NULL;
+ Py_buffer input_chunk_buf;
PyObject *decoded_chars, *chunk_size;
Py_ssize_t nbytes, nchars;
int eof;
@@ -1468,7 +1449,16 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint)
/* Given this, we know there was a valid snapshot point
* len(dec_buffer) bytes ago with decoder state (b'', dec_flags).
*/
- if (PyArg_Parse(state, "(OO)", &dec_buffer, &dec_flags) < 0) {
+ if (PyArg_ParseTuple(state, "OO", &dec_buffer, &dec_flags) < 0) {
+ Py_DECREF(state);
+ return -1;
+ }
+
+ if (!PyBytes_Check(dec_buffer)) {
+ PyErr_Format(PyExc_TypeError,
+ "decoder getstate() should have returned a bytes "
+ "object, not '%.200s'",
+ Py_TYPE(dec_buffer)->tp_name);
Py_DECREF(state);
return -1;
}
@@ -1484,23 +1474,24 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint)
chunk_size = PyLong_FromSsize_t(Py_MAX(self->chunk_size, size_hint));
if (chunk_size == NULL)
goto fail;
+
input_chunk = PyObject_CallMethodObjArgs(self->buffer,
(self->has_read1 ? _PyIO_str_read1: _PyIO_str_read),
chunk_size, NULL);
Py_DECREF(chunk_size);
if (input_chunk == NULL)
goto fail;
- if (!PyBytes_Check(input_chunk)) {
+
+ if (PyObject_GetBuffer(input_chunk, &input_chunk_buf, 0) != 0) {
PyErr_Format(PyExc_TypeError,
- "underlying %s() should have returned a bytes object, "
+ "underlying %s() should have returned a bytes-like object, "
"not '%.200s'", (self->has_read1 ? "read1": "read"),
Py_TYPE(input_chunk)->tp_name);
goto fail;
}
- nbytes = PyBytes_Size(input_chunk);
+ nbytes = input_chunk_buf.len;
eof = (nbytes == 0);
-
if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type) {
decoded_chars = _PyIncrementalNewlineDecoder_decode(
self->decoder, input_chunk, eof);
@@ -1509,6 +1500,7 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint)
decoded_chars = PyObject_CallMethodObjArgs(self->decoder,
_PyIO_str_decode, input_chunk, eof ? Py_True : Py_False, NULL);
}
+ PyBuffer_Release(&input_chunk_buf);
if (check_decoded(decoded_chars) < 0)
goto fail;
@@ -1525,18 +1517,12 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint)
/* At the snapshot point, len(dec_buffer) bytes before the read, the
* next input to be decoded is dec_buffer + input_chunk.
*/
- PyObject *next_input = PyNumber_Add(dec_buffer, input_chunk);
- if (next_input == NULL)
- goto fail;
- if (!PyBytes_Check(next_input)) {
- PyErr_Format(PyExc_TypeError,
- "decoder getstate() should have returned a bytes "
- "object, not '%.200s'",
- Py_TYPE(next_input)->tp_name);
- Py_DECREF(next_input);
+ PyObject *next_input = dec_buffer;
+ PyBytes_Concat(&next_input, input_chunk);
+ if (next_input == NULL) {
+ dec_buffer = NULL; /* Reference lost to PyBytes_Concat */
goto fail;
}
- Py_DECREF(dec_buffer);
Py_CLEAR(self->snapshot);
self->snapshot = Py_BuildValue("NN", dec_flags, next_input);
}
@@ -1551,17 +1537,19 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint)
return -1;
}
+/*[clinic input]
+_io.TextIOWrapper.read
+ size as n: io_ssize_t = -1
+ /
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_read(textio *self, PyObject *args)
+_io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n)
+/*[clinic end generated code: output=7e651ce6cc6a25a6 input=8c09398424085cca]*/
{
- Py_ssize_t n = -1;
PyObject *result = NULL, *chunks = NULL;
CHECK_ATTACHED(self);
-
- if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n))
- return NULL;
-
CHECK_CLOSED(self);
if (self->decoder == NULL)
@@ -1725,7 +1713,7 @@ _PyIO_find_line_ending(
else {
/* Non-universal mode. */
Py_ssize_t readnl_len = PyUnicode_GET_LENGTH(readnl);
- char *nl = PyUnicode_DATA(readnl);
+ Py_UCS1 *nl = PyUnicode_1BYTE_DATA(readnl);
/* Assume that readnl is an ASCII character. */
assert(PyUnicode_KIND(readnl) == PyUnicode_1BYTE_KIND);
if (readnl_len == 1) {
@@ -1927,16 +1915,18 @@ _textiowrapper_readline(textio *self, Py_ssize_t limit)
return NULL;
}
+/*[clinic input]
+_io.TextIOWrapper.readline
+ size: Py_ssize_t = -1
+ /
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_readline(textio *self, PyObject *args)
+_io_TextIOWrapper_readline_impl(textio *self, Py_ssize_t size)
+/*[clinic end generated code: output=344afa98804e8b25 input=56c7172483b36db6]*/
{
- Py_ssize_t limit = -1;
-
CHECK_ATTACHED(self);
- if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
- return NULL;
- }
- return _textiowrapper_readline(self, limit);
+ return _textiowrapper_readline(self, size);
}
/* Seek and Tell */
@@ -2068,19 +2058,23 @@ _textiowrapper_encoder_setstate(textio *self, cookie_type *cookie)
self, cookie->start_pos == 0 && cookie->dec_flags == 0);
}
+/*[clinic input]
+_io.TextIOWrapper.seek
+ cookie as cookieObj: object
+ whence: int = 0
+ /
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_seek(textio *self, PyObject *args)
+_io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence)
+/*[clinic end generated code: output=0a15679764e2d04d input=0458abeb3d7842be]*/
{
- PyObject *cookieObj, *posobj;
+ PyObject *posobj;
cookie_type cookie;
- int whence = 0;
PyObject *res;
int cmp;
CHECK_ATTACHED(self);
-
- if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence))
- return NULL;
CHECK_CLOSED(self);
Py_INCREF(cookieObj);
@@ -2252,8 +2246,13 @@ textiowrapper_seek(textio *self, PyObject *args)
}
+/*[clinic input]
+_io.TextIOWrapper.tell
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_tell(textio *self, PyObject *args)
+_io_TextIOWrapper_tell_impl(textio *self)
+/*[clinic end generated code: output=4f168c08bf34ad5f input=9a2caf88c24f9ddf]*/
{
PyObject *res;
PyObject *posobj = NULL;
@@ -2263,7 +2262,6 @@ textiowrapper_tell(textio *self, PyObject *args)
Py_ssize_t skip_bytes, skip_back;
PyObject *saved_state = NULL;
char *input, *input_end;
- char *dec_buffer;
Py_ssize_t dec_buffer_len;
int dec_flags;
@@ -2306,7 +2304,7 @@ textiowrapper_tell(textio *self, PyObject *args)
goto fail;
/* Skip backward to the snapshot point (see _read_chunk). */
- if (!PyArg_Parse(self->snapshot, "(iO)", &cookie.dec_flags, &next_input))
+ if (!PyArg_ParseTuple(self->snapshot, "iO", &cookie.dec_flags, &next_input))
goto fail;
assert (PyBytes_Check(next_input));
@@ -2328,14 +2326,24 @@ textiowrapper_tell(textio *self, PyObject *args)
goto fail;
#define DECODER_GETSTATE() do { \
+ PyObject *dec_buffer; \
PyObject *_state = PyObject_CallMethodObjArgs(self->decoder, \
_PyIO_str_getstate, NULL); \
if (_state == NULL) \
goto fail; \
- if (!PyArg_Parse(_state, "(y#i)", &dec_buffer, &dec_buffer_len, &dec_flags)) { \
+ if (!PyArg_ParseTuple(_state, "Oi", &dec_buffer, &dec_flags)) { \
+ Py_DECREF(_state); \
+ goto fail; \
+ } \
+ if (!PyBytes_Check(dec_buffer)) { \
+ PyErr_Format(PyExc_TypeError, \
+ "decoder getstate() should have returned a bytes " \
+ "object, not '%.200s'", \
+ Py_TYPE(dec_buffer)->tp_name); \
Py_DECREF(_state); \
goto fail; \
} \
+ dec_buffer_len = PyBytes_GET_SIZE(dec_buffer); \
Py_DECREF(_state); \
} while (0)
@@ -2460,16 +2468,19 @@ fail:
return NULL;
}
+/*[clinic input]
+_io.TextIOWrapper.truncate
+ pos: object = None
+ /
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_truncate(textio *self, PyObject *args)
+_io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos)
+/*[clinic end generated code: output=90ec2afb9bb7745f input=56ec8baa65aea377]*/
{
- PyObject *pos = Py_None;
PyObject *res;
CHECK_ATTACHED(self)
- if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
- return NULL;
- }
res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_flush, NULL);
if (res == NULL)
@@ -2534,36 +2545,61 @@ error:
/* Inquiries */
+/*[clinic input]
+_io.TextIOWrapper.fileno
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_fileno(textio *self, PyObject *args)
+_io_TextIOWrapper_fileno_impl(textio *self)
+/*[clinic end generated code: output=21490a4c3da13e6c input=c488ca83d0069f9b]*/
{
CHECK_ATTACHED(self);
return _PyObject_CallMethodId(self->buffer, &PyId_fileno, NULL);
}
+/*[clinic input]
+_io.TextIOWrapper.seekable
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_seekable(textio *self, PyObject *args)
+_io_TextIOWrapper_seekable_impl(textio *self)
+/*[clinic end generated code: output=ab223dbbcffc0f00 input=8b005ca06e1fca13]*/
{
CHECK_ATTACHED(self);
return _PyObject_CallMethodId(self->buffer, &PyId_seekable, NULL);
}
+/*[clinic input]
+_io.TextIOWrapper.readable
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_readable(textio *self, PyObject *args)
+_io_TextIOWrapper_readable_impl(textio *self)
+/*[clinic end generated code: output=72ff7ba289a8a91b input=0704ea7e01b0d3eb]*/
{
CHECK_ATTACHED(self);
return _PyObject_CallMethodId(self->buffer, &PyId_readable, NULL);
}
+/*[clinic input]
+_io.TextIOWrapper.writable
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_writable(textio *self, PyObject *args)
+_io_TextIOWrapper_writable_impl(textio *self)
+/*[clinic end generated code: output=a728c71790d03200 input=c41740bc9d8636e8]*/
{
CHECK_ATTACHED(self);
return _PyObject_CallMethodId(self->buffer, &PyId_writable, NULL);
}
+/*[clinic input]
+_io.TextIOWrapper.isatty
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_isatty(textio *self, PyObject *args)
+_io_TextIOWrapper_isatty_impl(textio *self)
+/*[clinic end generated code: output=12be1a35bace882e input=fb68d9f2c99bbfff]*/
{
CHECK_ATTACHED(self);
return _PyObject_CallMethodId(self->buffer, &PyId_isatty, NULL);
@@ -2577,8 +2613,13 @@ textiowrapper_getstate(textio *self, PyObject *args)
return NULL;
}
+/*[clinic input]
+_io.TextIOWrapper.flush
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_flush(textio *self, PyObject *args)
+_io_TextIOWrapper_flush_impl(textio *self)
+/*[clinic end generated code: output=59de9165f9c2e4d2 input=928c60590694ab85]*/
{
CHECK_ATTACHED(self);
CHECK_CLOSED(self);
@@ -2588,8 +2629,13 @@ textiowrapper_flush(textio *self, PyObject *args)
return _PyObject_CallMethodId(self->buffer, &PyId_flush, NULL);
}
+/*[clinic input]
+_io.TextIOWrapper.close
+[clinic start generated code]*/
+
static PyObject *
-textiowrapper_close(textio *self, PyObject *args)
+_io_TextIOWrapper_close_impl(textio *self)
+/*[clinic end generated code: output=056ccf8b4876e4f4 input=9c2114315eae1948]*/
{
PyObject *res;
int r;
@@ -2733,24 +2779,81 @@ textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context)
return 0;
}
+#include "clinic/textio.c.h"
+
+static PyMethodDef incrementalnewlinedecoder_methods[] = {
+ _IO_INCREMENTALNEWLINEDECODER_DECODE_METHODDEF
+ _IO_INCREMENTALNEWLINEDECODER_GETSTATE_METHODDEF
+ _IO_INCREMENTALNEWLINEDECODER_SETSTATE_METHODDEF
+ _IO_INCREMENTALNEWLINEDECODER_RESET_METHODDEF
+ {NULL}
+};
+
+static PyGetSetDef incrementalnewlinedecoder_getset[] = {
+ {"newlines", (getter)incrementalnewlinedecoder_newlines_get, NULL, NULL},
+ {NULL}
+};
+
+PyTypeObject PyIncrementalNewlineDecoder_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "_io.IncrementalNewlineDecoder", /*tp_name*/
+ sizeof(nldecoder_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)incrementalnewlinedecoder_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare */
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ _io_IncrementalNewlineDecoder___init____doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /*tp_weaklistoffset*/
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ incrementalnewlinedecoder_methods, /* tp_methods */
+ 0, /* tp_members */
+ incrementalnewlinedecoder_getset, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ _io_IncrementalNewlineDecoder___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+
static PyMethodDef textiowrapper_methods[] = {
- {"detach", (PyCFunction)textiowrapper_detach, METH_NOARGS},
- {"write", (PyCFunction)textiowrapper_write, METH_VARARGS},
- {"read", (PyCFunction)textiowrapper_read, METH_VARARGS},
- {"readline", (PyCFunction)textiowrapper_readline, METH_VARARGS},
- {"flush", (PyCFunction)textiowrapper_flush, METH_NOARGS},
- {"close", (PyCFunction)textiowrapper_close, METH_NOARGS},
-
- {"fileno", (PyCFunction)textiowrapper_fileno, METH_NOARGS},
- {"seekable", (PyCFunction)textiowrapper_seekable, METH_NOARGS},
- {"readable", (PyCFunction)textiowrapper_readable, METH_NOARGS},
- {"writable", (PyCFunction)textiowrapper_writable, METH_NOARGS},
- {"isatty", (PyCFunction)textiowrapper_isatty, METH_NOARGS},
+ _IO_TEXTIOWRAPPER_DETACH_METHODDEF
+ _IO_TEXTIOWRAPPER_WRITE_METHODDEF
+ _IO_TEXTIOWRAPPER_READ_METHODDEF
+ _IO_TEXTIOWRAPPER_READLINE_METHODDEF
+ _IO_TEXTIOWRAPPER_FLUSH_METHODDEF
+ _IO_TEXTIOWRAPPER_CLOSE_METHODDEF
+
+ _IO_TEXTIOWRAPPER_FILENO_METHODDEF
+ _IO_TEXTIOWRAPPER_SEEKABLE_METHODDEF
+ _IO_TEXTIOWRAPPER_READABLE_METHODDEF
+ _IO_TEXTIOWRAPPER_WRITABLE_METHODDEF
+ _IO_TEXTIOWRAPPER_ISATTY_METHODDEF
{"__getstate__", (PyCFunction)textiowrapper_getstate, METH_NOARGS},
- {"seek", (PyCFunction)textiowrapper_seek, METH_VARARGS},
- {"tell", (PyCFunction)textiowrapper_tell, METH_NOARGS},
- {"truncate", (PyCFunction)textiowrapper_truncate, METH_VARARGS},
+ _IO_TEXTIOWRAPPER_SEEK_METHODDEF
+ _IO_TEXTIOWRAPPER_TELL_METHODDEF
+ _IO_TEXTIOWRAPPER_TRUNCATE_METHODDEF
{NULL, NULL}
};
@@ -2796,7 +2899,7 @@ PyTypeObject PyTextIOWrapper_Type = {
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
- textiowrapper_doc, /* tp_doc */
+ _io_TextIOWrapper___init____doc__, /* tp_doc */
(traverseproc)textiowrapper_traverse, /* tp_traverse */
(inquiry)textiowrapper_clear, /* tp_clear */
0, /* tp_richcompare */
@@ -2811,7 +2914,7 @@ PyTypeObject PyTextIOWrapper_Type = {
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(textio, dict), /*tp_dictoffset*/
- (initproc)textiowrapper_init, /* tp_init */
+ _io_TextIOWrapper___init__, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
0, /* tp_free */