12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061 |
- /*
- An implementation of the I/O abstract base classes hierarchy
- as defined by PEP 3116 - "New I/O"
- Classes defined here: IOBase, RawIOBase.
- Written by Amaury Forgeot d'Arc and Antoine Pitrou
- */
- #define PY_SSIZE_T_CLEAN
- #include "Python.h"
- #include "pycore_long.h" // _PyLong_GetOne()
- #include "pycore_object.h"
- #include <stddef.h> // offsetof()
- #include "_iomodule.h"
- /*[clinic input]
- module _io
- class _io._IOBase "PyObject *" "clinic_state()->PyIOBase_Type"
- class _io._RawIOBase "PyObject *" "clinic_state()->PyRawIOBase_Type"
- [clinic start generated code]*/
- /*[clinic end generated code: output=da39a3ee5e6b4b0d input=9006b7802ab8ea85]*/
- /*
- * IOBase class, an abstract class
- */
- typedef struct {
- PyObject_HEAD
- PyObject *dict;
- PyObject *weakreflist;
- } iobase;
- PyDoc_STRVAR(iobase_doc,
- "The abstract base class for all I/O classes.\n"
- "\n"
- "This class provides dummy implementations for many methods that\n"
- "derived classes can override selectively; the default implementations\n"
- "represent a file that cannot be read, written or seeked.\n"
- "\n"
- "Even though IOBase does not declare read, readinto, or write because\n"
- "their signatures will vary, implementations and clients should\n"
- "consider those methods part of the interface. Also, implementations\n"
- "may raise UnsupportedOperation when operations they do not support are\n"
- "called.\n"
- "\n"
- "The basic type used for binary data read from or written to a file is\n"
- "bytes. Other bytes-like objects are accepted as method arguments too.\n"
- "In some cases (such as readinto), a writable object is required. Text\n"
- "I/O classes work with str data.\n"
- "\n"
- "Note that calling any method (except additional calls to close(),\n"
- "which are ignored) on a closed stream should raise a ValueError.\n"
- "\n"
- "IOBase (and its subclasses) support the iterator protocol, meaning\n"
- "that an IOBase object can be iterated over yielding the lines in a\n"
- "stream.\n"
- "\n"
- "IOBase also supports the :keyword:`with` statement. In this example,\n"
- "fp is closed after the suite of the with statement is complete:\n"
- "\n"
- "with open('spam.txt', 'r') as fp:\n"
- " fp.write('Spam and eggs!')\n");
- /* Use this macro whenever you want to check the internal `closed` status
- of the IOBase object rather than the virtual `closed` attribute as returned
- by whatever subclass. */
- /* Internal methods */
- static PyObject *
- iobase_unsupported(_PyIO_State *state, const char *message)
- {
- PyErr_SetString(state->unsupported_operation, message);
- return NULL;
- }
- /* Positioning */
- /*[clinic input]
- _io._IOBase.seek
- cls: defining_class
- offset: int(unused=True)
- The stream position, relative to 'whence'.
- whence: int(unused=True, c_default='0') = os.SEEK_SET
- The relative position to seek from.
- /
- Change the stream position to the given byte offset.
- The offset is interpreted relative to the position indicated by whence.
- Values for whence are:
- * os.SEEK_SET or 0 -- start of stream (the default); offset should be zero or positive
- * os.SEEK_CUR or 1 -- current stream position; offset may be negative
- * os.SEEK_END or 2 -- end of stream; offset is usually negative
- Return the new absolute position.
- [clinic start generated code]*/
- static PyObject *
- _io__IOBase_seek_impl(PyObject *self, PyTypeObject *cls,
- int Py_UNUSED(offset), int Py_UNUSED(whence))
- /*[clinic end generated code: output=8bd74ea6538ded53 input=74211232b363363e]*/
- {
- _PyIO_State *state = get_io_state_by_cls(cls);
- return iobase_unsupported(state, "seek");
- }
- /*[clinic input]
- _io._IOBase.tell
- Return current stream position.
- [clinic start generated code]*/
- static PyObject *
- _io__IOBase_tell_impl(PyObject *self)
- /*[clinic end generated code: output=89a1c0807935abe2 input=04e615fec128801f]*/
- {
- return _PyObject_CallMethod(self, &_Py_ID(seek), "ii", 0, 1);
- }
- /*[clinic input]
- _io._IOBase.truncate
- cls: defining_class
- size: object(unused=True) = None
- /
- Truncate file to size bytes.
- File pointer is left unchanged. Size defaults to the current IO position
- as reported by tell(). Return the new size.
- [clinic start generated code]*/
- static PyObject *
- _io__IOBase_truncate_impl(PyObject *self, PyTypeObject *cls,
- PyObject *Py_UNUSED(size))
- /*[clinic end generated code: output=2013179bff1fe8ef input=660ac20936612c27]*/
- {
- _PyIO_State *state = get_io_state_by_cls(cls);
- return iobase_unsupported(state, "truncate");
- }
- static int
- iobase_is_closed(PyObject *self)
- {
- PyObject *res;
- int ret;
- /* This gets the derived attribute, which is *not* __IOBase_closed
- in most cases! */
- ret = _PyObject_LookupAttr(self, &_Py_ID(__IOBase_closed), &res);
- Py_XDECREF(res);
- return ret;
- }
- /* Flush and close methods */
- /*[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 *
- _io__IOBase_flush_impl(PyObject *self)
- /*[clinic end generated code: output=7cef4b4d54656a3b input=773be121abe270aa]*/
- {
- /* XXX Should this return the number of bytes written??? */
- int closed = iobase_is_closed(self);
- if (!closed) {
- Py_RETURN_NONE;
- }
- if (closed > 0) {
- PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
- }
- return NULL;
- }
- static PyObject *
- iobase_closed_get(PyObject *self, void *context)
- {
- int closed = iobase_is_closed(self);
- if (closed < 0) {
- return NULL;
- }
- return PyBool_FromLong(closed);
- }
- static int
- iobase_check_closed(PyObject *self)
- {
- PyObject *res;
- int closed;
- /* This gets the derived attribute, which is *not* __IOBase_closed
- in most cases! */
- closed = _PyObject_LookupAttr(self, &_Py_ID(closed), &res);
- if (closed > 0) {
- closed = PyObject_IsTrue(res);
- Py_DECREF(res);
- if (closed > 0) {
- PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
- return -1;
- }
- }
- return closed;
- }
- PyObject *
- _PyIOBase_check_closed(PyObject *self, PyObject *args)
- {
- if (iobase_check_closed(self)) {
- return NULL;
- }
- if (args == Py_True) {
- return Py_None;
- }
- Py_RETURN_NONE;
- }
- static PyObject *
- iobase_check_seekable(PyObject *self, PyObject *args)
- {
- _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
- return _PyIOBase_check_seekable(state, self, args);
- }
- static PyObject *
- iobase_check_readable(PyObject *self, PyObject *args)
- {
- _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
- return _PyIOBase_check_readable(state, self, args);
- }
- static PyObject *
- iobase_check_writable(PyObject *self, PyObject *args)
- {
- _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
- return _PyIOBase_check_writable(state, self, args);
- }
- PyObject *
- _PyIOBase_cannot_pickle(PyObject *self, PyObject *args)
- {
- PyErr_Format(PyExc_TypeError,
- "cannot pickle '%.100s' instances", _PyType_Name(Py_TYPE(self)));
- return NULL;
- }
- /* XXX: IOBase thinks it has to maintain its own internal state in
- `__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 *
- _io__IOBase_close_impl(PyObject *self)
- /*[clinic end generated code: output=63c6a6f57d783d6d input=f4494d5c31dbc6b7]*/
- {
- int rc, closed = iobase_is_closed(self);
- if (closed < 0) {
- return NULL;
- }
- if (closed) {
- Py_RETURN_NONE;
- }
- PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(flush));
- PyObject *exc = PyErr_GetRaisedException();
- rc = PyObject_SetAttr(self, &_Py_ID(__IOBase_closed), Py_True);
- _PyErr_ChainExceptions1(exc);
- if (rc < 0) {
- Py_CLEAR(res);
- }
- if (res == NULL)
- return NULL;
- Py_DECREF(res);
- Py_RETURN_NONE;
- }
- /* Finalization and garbage collection support */
- static void
- iobase_finalize(PyObject *self)
- {
- PyObject *res;
- int closed;
- /* Save the current exception, if any. */
- PyObject *exc = PyErr_GetRaisedException();
- /* If `closed` doesn't exist or can't be evaluated as bool, then the
- object is probably in an unusable state, so ignore. */
- if (_PyObject_LookupAttr(self, &_Py_ID(closed), &res) <= 0) {
- PyErr_Clear();
- closed = -1;
- }
- else {
- closed = PyObject_IsTrue(res);
- Py_DECREF(res);
- if (closed == -1)
- PyErr_Clear();
- }
- if (closed == 0) {
- /* Signal close() that it was called as part of the object
- finalization process. */
- if (PyObject_SetAttr(self, &_Py_ID(_finalizing), Py_True))
- PyErr_Clear();
- res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(close));
- /* Silencing I/O errors is bad, but printing spurious tracebacks is
- equally as bad, and potentially more frequent (because of
- shutdown issues). */
- if (res == NULL) {
- #ifndef Py_DEBUG
- if (_Py_GetConfig()->dev_mode) {
- PyErr_WriteUnraisable(self);
- }
- else {
- PyErr_Clear();
- }
- #else
- PyErr_WriteUnraisable(self);
- #endif
- }
- else {
- Py_DECREF(res);
- }
- }
- /* Restore the saved exception. */
- PyErr_SetRaisedException(exc);
- }
- int
- _PyIOBase_finalize(PyObject *self)
- {
- int is_zombie;
- /* If _PyIOBase_finalize() is called from a destructor, we need to
- resurrect the object as calling close() can invoke arbitrary code. */
- is_zombie = (Py_REFCNT(self) == 0);
- if (is_zombie)
- return PyObject_CallFinalizerFromDealloc(self);
- else {
- PyObject_CallFinalizer(self);
- return 0;
- }
- }
- static int
- iobase_traverse(iobase *self, visitproc visit, void *arg)
- {
- Py_VISIT(Py_TYPE(self));
- Py_VISIT(self->dict);
- return 0;
- }
- static int
- iobase_clear(iobase *self)
- {
- Py_CLEAR(self->dict);
- return 0;
- }
- /* Destructor */
- static void
- iobase_dealloc(iobase *self)
- {
- /* NOTE: since IOBaseObject has its own dict, Python-defined attributes
- are still available here for close() to use.
- However, if the derived class declares a __slots__, those slots are
- already gone.
- */
- if (_PyIOBase_finalize((PyObject *) self) < 0) {
- /* When called from a heap type's dealloc, the type will be
- decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */
- if (_PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) {
- Py_INCREF(Py_TYPE(self));
- }
- return;
- }
- PyTypeObject *tp = Py_TYPE(self);
- _PyObject_GC_UNTRACK(self);
- if (self->weakreflist != NULL)
- PyObject_ClearWeakRefs((PyObject *) self);
- Py_CLEAR(self->dict);
- tp->tp_free((PyObject *)self);
- Py_DECREF(tp);
- }
- /* Inquiry methods */
- /*[clinic input]
- _io._IOBase.seekable
- Return whether object supports random access.
- If False, seek(), tell() and truncate() will raise OSError.
- This method may need to do a test seek().
- [clinic start generated code]*/
- static PyObject *
- _io__IOBase_seekable_impl(PyObject *self)
- /*[clinic end generated code: output=4c24c67f5f32a43d input=b976622f7fdf3063]*/
- {
- Py_RETURN_FALSE;
- }
- PyObject *
- _PyIOBase_check_seekable(_PyIO_State *state, PyObject *self, PyObject *args)
- {
- PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(seekable));
- if (res == NULL)
- return NULL;
- if (res != Py_True) {
- Py_CLEAR(res);
- iobase_unsupported(state, "File or stream is not seekable.");
- return NULL;
- }
- if (args == Py_True) {
- Py_DECREF(res);
- }
- return res;
- }
- /*[clinic input]
- _io._IOBase.readable
- Return whether object was opened for reading.
- If False, read() will raise OSError.
- [clinic start generated code]*/
- static PyObject *
- _io__IOBase_readable_impl(PyObject *self)
- /*[clinic end generated code: output=e48089250686388b input=285b3b866a0ec35f]*/
- {
- Py_RETURN_FALSE;
- }
- /* May be called with any object */
- PyObject *
- _PyIOBase_check_readable(_PyIO_State *state, PyObject *self, PyObject *args)
- {
- PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(readable));
- if (res == NULL)
- return NULL;
- if (res != Py_True) {
- Py_CLEAR(res);
- iobase_unsupported(state, "File or stream is not readable.");
- return NULL;
- }
- if (args == Py_True) {
- Py_DECREF(res);
- }
- return res;
- }
- /*[clinic input]
- _io._IOBase.writable
- Return whether object was opened for writing.
- If False, write() will raise OSError.
- [clinic start generated code]*/
- static PyObject *
- _io__IOBase_writable_impl(PyObject *self)
- /*[clinic end generated code: output=406001d0985be14f input=9dcac18a013a05b5]*/
- {
- Py_RETURN_FALSE;
- }
- /* May be called with any object */
- PyObject *
- _PyIOBase_check_writable(_PyIO_State *state, PyObject *self, PyObject *args)
- {
- PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(writable));
- if (res == NULL)
- return NULL;
- if (res != Py_True) {
- Py_CLEAR(res);
- iobase_unsupported(state, "File or stream is not writable.");
- return NULL;
- }
- if (args == Py_True) {
- Py_DECREF(res);
- }
- return res;
- }
- /* Context manager */
- static PyObject *
- iobase_enter(PyObject *self, PyObject *args)
- {
- if (iobase_check_closed(self))
- return NULL;
- return Py_NewRef(self);
- }
- static PyObject *
- iobase_exit(PyObject *self, PyObject *args)
- {
- return PyObject_CallMethodNoArgs(self, &_Py_ID(close));
- }
- /* Lower-level APIs */
- /* XXX Should these be present even if unimplemented? */
- /*[clinic input]
- _io._IOBase.fileno
- cls: defining_class
- /
- Return underlying file descriptor if one exists.
- Raise OSError if the IO object does not use a file descriptor.
- [clinic start generated code]*/
- static PyObject *
- _io__IOBase_fileno_impl(PyObject *self, PyTypeObject *cls)
- /*[clinic end generated code: output=7caaa32a6f4ada3d input=1927c8bea5c85099]*/
- {
- _PyIO_State *state = get_io_state_by_cls(cls);
- return iobase_unsupported(state, "fileno");
- }
- /*[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 *
- _io__IOBase_isatty_impl(PyObject *self)
- /*[clinic end generated code: output=60cab77cede41cdd input=9ef76530d368458b]*/
- {
- if (iobase_check_closed(self))
- return NULL;
- Py_RETURN_FALSE;
- }
- /* Readline(s) and writelines */
- /*[clinic input]
- _io._IOBase.readline
- size as limit: Py_ssize_t(accept={int, NoneType}) = -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 *
- _io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit)
- /*[clinic end generated code: output=4479f79b58187840 input=d0c596794e877bff]*/
- {
- /* For backwards compatibility, a (slowish) readline(). */
- PyObject *peek, *buffer, *result;
- Py_ssize_t old_size = -1;
- if (_PyObject_LookupAttr(self, &_Py_ID(peek), &peek) < 0) {
- return NULL;
- }
- buffer = PyByteArray_FromStringAndSize(NULL, 0);
- if (buffer == NULL) {
- Py_XDECREF(peek);
- return NULL;
- }
- while (limit < 0 || PyByteArray_GET_SIZE(buffer) < limit) {
- Py_ssize_t nreadahead = 1;
- PyObject *b;
- if (peek != NULL) {
- PyObject *readahead = PyObject_CallOneArg(peek, _PyLong_GetOne());
- if (readahead == NULL) {
- /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
- when EINTR occurs so we needn't do it ourselves. */
- if (_PyIO_trap_eintr()) {
- continue;
- }
- goto fail;
- }
- if (!PyBytes_Check(readahead)) {
- PyErr_Format(PyExc_OSError,
- "peek() should have returned a bytes object, "
- "not '%.200s'", Py_TYPE(readahead)->tp_name);
- Py_DECREF(readahead);
- goto fail;
- }
- if (PyBytes_GET_SIZE(readahead) > 0) {
- Py_ssize_t n = 0;
- const char *buf = PyBytes_AS_STRING(readahead);
- if (limit >= 0) {
- do {
- if (n >= PyBytes_GET_SIZE(readahead) || n >= limit)
- break;
- if (buf[n++] == '\n')
- break;
- } while (1);
- }
- else {
- do {
- if (n >= PyBytes_GET_SIZE(readahead))
- break;
- if (buf[n++] == '\n')
- break;
- } while (1);
- }
- nreadahead = n;
- }
- Py_DECREF(readahead);
- }
- b = _PyObject_CallMethod(self, &_Py_ID(read), "n", nreadahead);
- if (b == NULL) {
- /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
- when EINTR occurs so we needn't do it ourselves. */
- if (_PyIO_trap_eintr()) {
- continue;
- }
- goto fail;
- }
- if (!PyBytes_Check(b)) {
- PyErr_Format(PyExc_OSError,
- "read() should have returned a bytes object, "
- "not '%.200s'", Py_TYPE(b)->tp_name);
- Py_DECREF(b);
- goto fail;
- }
- if (PyBytes_GET_SIZE(b) == 0) {
- Py_DECREF(b);
- break;
- }
- old_size = PyByteArray_GET_SIZE(buffer);
- if (PyByteArray_Resize(buffer, old_size + PyBytes_GET_SIZE(b)) < 0) {
- Py_DECREF(b);
- goto fail;
- }
- memcpy(PyByteArray_AS_STRING(buffer) + old_size,
- PyBytes_AS_STRING(b), PyBytes_GET_SIZE(b));
- Py_DECREF(b);
- if (PyByteArray_AS_STRING(buffer)[PyByteArray_GET_SIZE(buffer) - 1] == '\n')
- break;
- }
- result = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(buffer),
- PyByteArray_GET_SIZE(buffer));
- Py_XDECREF(peek);
- Py_DECREF(buffer);
- return result;
- fail:
- Py_XDECREF(peek);
- Py_DECREF(buffer);
- return NULL;
- }
- static PyObject *
- iobase_iter(PyObject *self)
- {
- if (iobase_check_closed(self))
- return NULL;
- return Py_NewRef(self);
- }
- static PyObject *
- iobase_iternext(PyObject *self)
- {
- PyObject *line = PyObject_CallMethodNoArgs(self, &_Py_ID(readline));
- if (line == NULL)
- return NULL;
- if (PyObject_Size(line) <= 0) {
- /* Error or empty */
- Py_DECREF(line);
- return NULL;
- }
- return line;
- }
- /*[clinic input]
- _io._IOBase.readlines
- hint: Py_ssize_t(accept={int, NoneType}) = -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 *
- _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint)
- /*[clinic end generated code: output=2f50421677fa3dea input=9400c786ea9dc416]*/
- {
- Py_ssize_t length = 0;
- PyObject *result, *it = NULL;
- result = PyList_New(0);
- if (result == NULL)
- return NULL;
- if (hint <= 0) {
- /* XXX special-casing this made sense in the Python version in order
- to remove the bytecode interpretation overhead, but it could
- probably be removed here. */
- PyObject *ret = PyObject_CallMethodObjArgs(result, &_Py_ID(extend),
- self, NULL);
- if (ret == NULL) {
- goto error;
- }
- Py_DECREF(ret);
- return result;
- }
- it = PyObject_GetIter(self);
- if (it == NULL) {
- goto error;
- }
- while (1) {
- Py_ssize_t line_length;
- PyObject *line = PyIter_Next(it);
- if (line == NULL) {
- if (PyErr_Occurred()) {
- goto error;
- }
- else
- break; /* StopIteration raised */
- }
- if (PyList_Append(result, line) < 0) {
- Py_DECREF(line);
- goto error;
- }
- line_length = PyObject_Size(line);
- Py_DECREF(line);
- if (line_length < 0) {
- goto error;
- }
- if (line_length > hint - length)
- break;
- length += line_length;
- }
- Py_DECREF(it);
- return result;
- error:
- Py_XDECREF(it);
- Py_DECREF(result);
- return NULL;
- }
- /*[clinic input]
- _io._IOBase.writelines
- lines: object
- /
- Write a list of lines to stream.
- Line separators are not added, so it is usual for each of the
- lines provided to have a line separator at the end.
- [clinic start generated code]*/
- static PyObject *
- _io__IOBase_writelines(PyObject *self, PyObject *lines)
- /*[clinic end generated code: output=976eb0a9b60a6628 input=cac3fc8864183359]*/
- {
- PyObject *iter, *res;
- if (iobase_check_closed(self))
- return NULL;
- iter = PyObject_GetIter(lines);
- if (iter == NULL)
- return NULL;
- while (1) {
- PyObject *line = PyIter_Next(iter);
- if (line == NULL) {
- if (PyErr_Occurred()) {
- Py_DECREF(iter);
- return NULL;
- }
- else
- break; /* Stop Iteration */
- }
- res = NULL;
- do {
- res = PyObject_CallMethodObjArgs(self, &_Py_ID(write), line, NULL);
- } while (res == NULL && _PyIO_trap_eintr());
- Py_DECREF(line);
- if (res == NULL) {
- Py_DECREF(iter);
- return NULL;
- }
- Py_DECREF(res);
- }
- Py_DECREF(iter);
- Py_RETURN_NONE;
- }
- #define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
- #include "clinic/iobase.c.h"
- #undef clinic_state
- static PyMethodDef iobase_methods[] = {
- _IO__IOBASE_SEEK_METHODDEF
- _IO__IOBASE_TELL_METHODDEF
- _IO__IOBASE_TRUNCATE_METHODDEF
- _IO__IOBASE_FLUSH_METHODDEF
- _IO__IOBASE_CLOSE_METHODDEF
- _IO__IOBASE_SEEKABLE_METHODDEF
- _IO__IOBASE_READABLE_METHODDEF
- _IO__IOBASE_WRITABLE_METHODDEF
- {"_checkClosed", _PyIOBase_check_closed, METH_NOARGS},
- {"_checkSeekable", iobase_check_seekable, METH_NOARGS},
- {"_checkReadable", iobase_check_readable, METH_NOARGS},
- {"_checkWritable", iobase_check_writable, METH_NOARGS},
- _IO__IOBASE_FILENO_METHODDEF
- _IO__IOBASE_ISATTY_METHODDEF
- {"__enter__", iobase_enter, METH_NOARGS},
- {"__exit__", iobase_exit, METH_VARARGS},
- _IO__IOBASE_READLINE_METHODDEF
- _IO__IOBASE_READLINES_METHODDEF
- _IO__IOBASE_WRITELINES_METHODDEF
- {NULL, NULL}
- };
- static PyGetSetDef iobase_getset[] = {
- {"__dict__", PyObject_GenericGetDict, NULL, NULL},
- {"closed", (getter)iobase_closed_get, NULL, NULL},
- {NULL}
- };
- static struct PyMemberDef iobase_members[] = {
- {"__weaklistoffset__", T_PYSSIZET, offsetof(iobase, weakreflist), READONLY},
- {"__dictoffset__", T_PYSSIZET, offsetof(iobase, dict), READONLY},
- {NULL},
- };
- static PyType_Slot iobase_slots[] = {
- {Py_tp_dealloc, iobase_dealloc},
- {Py_tp_doc, (void *)iobase_doc},
- {Py_tp_traverse, iobase_traverse},
- {Py_tp_clear, iobase_clear},
- {Py_tp_iter, iobase_iter},
- {Py_tp_iternext, iobase_iternext},
- {Py_tp_methods, iobase_methods},
- {Py_tp_members, iobase_members},
- {Py_tp_getset, iobase_getset},
- {Py_tp_finalize, iobase_finalize},
- {0, NULL},
- };
- PyType_Spec iobase_spec = {
- .name = "_io._IOBase",
- .basicsize = sizeof(iobase),
- .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
- Py_TPFLAGS_IMMUTABLETYPE),
- .slots = iobase_slots,
- };
- /*
- * RawIOBase class, Inherits from IOBase.
- */
- PyDoc_STRVAR(rawiobase_doc,
- "Base class for raw binary I/O.");
- /*
- * The read() method is implemented by calling readinto(); derived classes
- * that want to support read() only need to implement readinto() as a
- * primitive operation. In general, readinto() can be more efficient than
- * read().
- *
- * (It would be tempting to also provide an implementation of readinto() in
- * terms of read(), in case the latter is a more suitable primitive operation,
- * but that would lead to nasty recursion in case a subclass doesn't implement
- * either.)
- */
- /*[clinic input]
- _io._RawIOBase.read
- size as n: Py_ssize_t = -1
- /
- [clinic start generated code]*/
- static PyObject *
- _io__RawIOBase_read_impl(PyObject *self, Py_ssize_t n)
- /*[clinic end generated code: output=6cdeb731e3c9f13c input=b6d0dcf6417d1374]*/
- {
- PyObject *b, *res;
- if (n < 0) {
- return PyObject_CallMethodNoArgs(self, &_Py_ID(readall));
- }
- /* TODO: allocate a bytes object directly instead and manually construct
- a writable memoryview pointing to it. */
- b = PyByteArray_FromStringAndSize(NULL, n);
- if (b == NULL)
- return NULL;
- res = PyObject_CallMethodObjArgs(self, &_Py_ID(readinto), b, NULL);
- if (res == NULL || res == Py_None) {
- Py_DECREF(b);
- return res;
- }
- n = PyNumber_AsSsize_t(res, PyExc_ValueError);
- Py_DECREF(res);
- if (n == -1 && PyErr_Occurred()) {
- Py_DECREF(b);
- return NULL;
- }
- res = PyBytes_FromStringAndSize(PyByteArray_AsString(b), n);
- Py_DECREF(b);
- return res;
- }
- /*[clinic input]
- _io._RawIOBase.readall
- Read until EOF, using multiple read() call.
- [clinic start generated code]*/
- static PyObject *
- _io__RawIOBase_readall_impl(PyObject *self)
- /*[clinic end generated code: output=1987b9ce929425a0 input=688874141213622a]*/
- {
- int r;
- PyObject *chunks = PyList_New(0);
- PyObject *result;
- if (chunks == NULL)
- return NULL;
- while (1) {
- PyObject *data = _PyObject_CallMethod(self, &_Py_ID(read),
- "i", DEFAULT_BUFFER_SIZE);
- if (!data) {
- /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
- when EINTR occurs so we needn't do it ourselves. */
- if (_PyIO_trap_eintr()) {
- continue;
- }
- Py_DECREF(chunks);
- return NULL;
- }
- if (data == Py_None) {
- if (PyList_GET_SIZE(chunks) == 0) {
- Py_DECREF(chunks);
- return data;
- }
- Py_DECREF(data);
- break;
- }
- if (!PyBytes_Check(data)) {
- Py_DECREF(chunks);
- Py_DECREF(data);
- PyErr_SetString(PyExc_TypeError, "read() should return bytes");
- return NULL;
- }
- if (PyBytes_GET_SIZE(data) == 0) {
- /* EOF */
- Py_DECREF(data);
- break;
- }
- r = PyList_Append(chunks, data);
- Py_DECREF(data);
- if (r < 0) {
- Py_DECREF(chunks);
- return NULL;
- }
- }
- result = _PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks);
- Py_DECREF(chunks);
- 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[] = {
- _IO__RAWIOBASE_READ_METHODDEF
- _IO__RAWIOBASE_READALL_METHODDEF
- {"readinto", rawiobase_readinto, METH_VARARGS},
- {"write", rawiobase_write, METH_VARARGS},
- {NULL, NULL}
- };
- static PyType_Slot rawiobase_slots[] = {
- {Py_tp_doc, (void *)rawiobase_doc},
- {Py_tp_methods, rawiobase_methods},
- {0, NULL},
- };
- /* Do not set Py_TPFLAGS_HAVE_GC so that tp_traverse and tp_clear are inherited */
- PyType_Spec rawiobase_spec = {
- .name = "_io._RawIOBase",
- .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
- Py_TPFLAGS_IMMUTABLETYPE),
- .slots = rawiobase_slots,
- };
|