Coverage Report

Created: 2025-08-26 06:26

/src/cpython/Modules/_io/iobase.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
    An implementation of the I/O abstract base classes hierarchy
3
    as defined by PEP 3116 - "New I/O"
4
5
    Classes defined here: IOBase, RawIOBase.
6
7
    Written by Amaury Forgeot d'Arc and Antoine Pitrou
8
*/
9
10
11
#include "Python.h"
12
#include "pycore_call.h"          // _PyObject_CallMethod()
13
#include "pycore_fileutils.h"           // _PyFile_Flush
14
#include "pycore_long.h"          // _PyLong_GetOne()
15
#include "pycore_object.h"        // _PyType_HasFeature()
16
#include "pycore_pyerrors.h"      // _PyErr_ChainExceptions1()
17
#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
18
19
#include <stddef.h>               // offsetof()
20
#include "_iomodule.h"
21
22
/*[clinic input]
23
module _io
24
class _io._IOBase "PyObject *" "clinic_state()->PyIOBase_Type"
25
class _io._RawIOBase "PyObject *" "clinic_state()->PyRawIOBase_Type"
26
[clinic start generated code]*/
27
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9006b7802ab8ea85]*/
28
29
/*
30
 * IOBase class, an abstract class
31
 */
32
33
typedef struct {
34
    PyObject_HEAD
35
36
    PyObject *dict;
37
    PyObject *weakreflist;
38
} iobase;
39
40
12.3k
#define iobase_CAST(op) ((iobase *)(op))
41
42
PyDoc_STRVAR(iobase_doc,
43
    "The abstract base class for all I/O classes.\n"
44
    "\n"
45
    "This class provides dummy implementations for many methods that\n"
46
    "derived classes can override selectively; the default implementations\n"
47
    "represent a file that cannot be read, written or seeked.\n"
48
    "\n"
49
    "Even though IOBase does not declare read, readinto, or write because\n"
50
    "their signatures will vary, implementations and clients should\n"
51
    "consider those methods part of the interface. Also, implementations\n"
52
    "may raise UnsupportedOperation when operations they do not support are\n"
53
    "called.\n"
54
    "\n"
55
    "The basic type used for binary data read from or written to a file is\n"
56
    "bytes. Other bytes-like objects are accepted as method arguments too.\n"
57
    "In some cases (such as readinto), a writable object is required. Text\n"
58
    "I/O classes work with str data.\n"
59
    "\n"
60
    "Note that calling any method (except additional calls to close(),\n"
61
    "which are ignored) on a closed stream should raise a ValueError.\n"
62
    "\n"
63
    "IOBase (and its subclasses) support the iterator protocol, meaning\n"
64
    "that an IOBase object can be iterated over yielding the lines in a\n"
65
    "stream.\n"
66
    "\n"
67
    "IOBase also supports the :keyword:`with` statement. In this example,\n"
68
    "fp is closed after the suite of the with statement is complete:\n"
69
    "\n"
70
    "with open('spam.txt', 'r') as fp:\n"
71
    "    fp.write('Spam and eggs!')\n");
72
73
74
/* Internal methods */
75
76
/* Use this function whenever you want to check the internal `closed` status
77
   of the IOBase object rather than the virtual `closed` attribute as returned
78
   by whatever subclass. */
79
80
static int
81
iobase_is_closed(PyObject *self)
82
32.2k
{
83
32.2k
    return PyObject_HasAttrWithError(self, &_Py_ID(__IOBase_closed));
84
32.2k
}
85
86
static PyObject *
87
iobase_unsupported(_PyIO_State *state, const char *message)
88
0
{
89
0
    PyErr_SetString(state->unsupported_operation, message);
90
0
    return NULL;
91
0
}
92
93
/* Positioning */
94
95
/*[clinic input]
96
@permit_long_docstring_body
97
_io._IOBase.seek
98
    cls: defining_class
99
    offset: int(unused=True)
100
      The stream position, relative to 'whence'.
101
    whence: int(unused=True, c_default='0') = os.SEEK_SET
102
      The relative position to seek from.
103
    /
104
105
Change the stream position to the given byte offset.
106
107
The offset is interpreted relative to the position indicated by whence.
108
Values for whence are:
109
110
* os.SEEK_SET or 0 -- start of stream (the default); offset should be zero or positive
111
* os.SEEK_CUR or 1 -- current stream position; offset may be negative
112
* os.SEEK_END or 2 -- end of stream; offset is usually negative
113
114
Return the new absolute position.
115
[clinic start generated code]*/
116
117
static PyObject *
118
_io__IOBase_seek_impl(PyObject *self, PyTypeObject *cls,
119
                      int Py_UNUSED(offset), int Py_UNUSED(whence))
120
/*[clinic end generated code: output=8bd74ea6538ded53 input=a21b5aad416ff6a9]*/
121
0
{
122
0
    _PyIO_State *state = get_io_state_by_cls(cls);
123
0
    return iobase_unsupported(state, "seek");
124
0
}
125
126
/*[clinic input]
127
_io._IOBase.tell
128
129
Return current stream position.
130
[clinic start generated code]*/
131
132
static PyObject *
133
_io__IOBase_tell_impl(PyObject *self)
134
/*[clinic end generated code: output=89a1c0807935abe2 input=04e615fec128801f]*/
135
0
{
136
0
    return _PyObject_CallMethod(self, &_Py_ID(seek), "ii", 0, 1);
137
0
}
138
139
/*[clinic input]
140
_io._IOBase.truncate
141
    cls: defining_class
142
    size: object(unused=True) = None
143
    /
144
145
Truncate file to size bytes.
146
147
File pointer is left unchanged. Size defaults to the current IO position
148
as reported by tell(). Return the new size.
149
[clinic start generated code]*/
150
151
static PyObject *
152
_io__IOBase_truncate_impl(PyObject *self, PyTypeObject *cls,
153
                          PyObject *Py_UNUSED(size))
154
/*[clinic end generated code: output=2013179bff1fe8ef input=660ac20936612c27]*/
155
0
{
156
0
    _PyIO_State *state = get_io_state_by_cls(cls);
157
0
    return iobase_unsupported(state, "truncate");
158
0
}
159
160
/* Flush and close methods */
161
162
/*[clinic input]
163
_io._IOBase.flush
164
165
Flush write buffers, if applicable.
166
167
This is not implemented for read-only and non-blocking streams.
168
[clinic start generated code]*/
169
170
static PyObject *
171
_io__IOBase_flush_impl(PyObject *self)
172
/*[clinic end generated code: output=7cef4b4d54656a3b input=773be121abe270aa]*/
173
11.8k
{
174
    /* XXX Should this return the number of bytes written??? */
175
11.8k
    int closed = iobase_is_closed(self);
176
177
11.8k
    if (!closed) {
178
11.8k
        Py_RETURN_NONE;
179
11.8k
    }
180
0
    if (closed > 0) {
181
0
        PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
182
0
    }
183
0
    return NULL;
184
11.8k
}
185
186
static PyObject *
187
iobase_closed_get(PyObject *self, void *context)
188
9.58k
{
189
9.58k
    int closed = iobase_is_closed(self);
190
9.58k
    if (closed < 0) {
191
0
        return NULL;
192
0
    }
193
9.58k
    return PyBool_FromLong(closed);
194
9.58k
}
195
196
static int
197
iobase_check_closed(PyObject *self)
198
40.6k
{
199
40.6k
    PyObject *res;
200
40.6k
    int closed;
201
    /* This gets the derived attribute, which is *not* __IOBase_closed
202
       in most cases! */
203
40.6k
    closed = PyObject_GetOptionalAttr(self, &_Py_ID(closed), &res);
204
40.6k
    if (closed > 0) {
205
40.6k
        closed = PyObject_IsTrue(res);
206
40.6k
        Py_DECREF(res);
207
40.6k
        if (closed > 0) {
208
0
            PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
209
0
            return -1;
210
0
        }
211
40.6k
    }
212
40.6k
    return closed;
213
40.6k
}
214
215
PyObject *
216
_PyIOBase_check_closed(PyObject *self, PyObject *args)
217
0
{
218
0
    if (iobase_check_closed(self)) {
219
0
        return NULL;
220
0
    }
221
0
    if (args == Py_True) {
222
0
        return Py_None;
223
0
    }
224
0
    Py_RETURN_NONE;
225
0
}
226
227
static PyObject *
228
iobase_check_seekable(PyObject *self, PyObject *args)
229
0
{
230
0
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
231
0
    return _PyIOBase_check_seekable(state, self, args);
232
0
}
233
234
static PyObject *
235
iobase_check_readable(PyObject *self, PyObject *args)
236
0
{
237
0
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
238
0
    return _PyIOBase_check_readable(state, self, args);
239
0
}
240
241
static PyObject *
242
iobase_check_writable(PyObject *self, PyObject *args)
243
0
{
244
0
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
245
0
    return _PyIOBase_check_writable(state, self, args);
246
0
}
247
248
PyObject *
249
_PyIOBase_cannot_pickle(PyObject *self, PyObject *args)
250
0
{
251
0
    PyErr_Format(PyExc_TypeError,
252
0
        "cannot pickle '%.100s' instances", _PyType_Name(Py_TYPE(self)));
253
0
    return NULL;
254
0
}
255
256
/* XXX: IOBase thinks it has to maintain its own internal state in
257
   `__IOBase_closed` and call flush() by itself, but it is redundant with
258
   whatever behaviour a non-trivial derived class will implement. */
259
260
/*[clinic input]
261
_io._IOBase.close
262
263
Flush and close the IO object.
264
265
This method has no effect if the file is already closed.
266
[clinic start generated code]*/
267
268
static PyObject *
269
_io__IOBase_close_impl(PyObject *self)
270
/*[clinic end generated code: output=63c6a6f57d783d6d input=f4494d5c31dbc6b7]*/
271
10.8k
{
272
10.8k
    int rc1, rc2, closed = iobase_is_closed(self);
273
274
10.8k
    if (closed < 0) {
275
0
        return NULL;
276
0
    }
277
10.8k
    if (closed) {
278
0
        Py_RETURN_NONE;
279
0
    }
280
281
10.8k
    rc1 = _PyFile_Flush(self);
282
10.8k
    PyObject *exc = PyErr_GetRaisedException();
283
10.8k
    rc2 = PyObject_SetAttr(self, &_Py_ID(__IOBase_closed), Py_True);
284
10.8k
    _PyErr_ChainExceptions1(exc);
285
10.8k
    if (rc1 < 0 || rc2 < 0) {
286
0
        return NULL;
287
0
    }
288
289
10.8k
    Py_RETURN_NONE;
290
10.8k
}
291
292
/* Finalization and garbage collection support */
293
294
static void
295
iobase_finalize(PyObject *self)
296
11.8k
{
297
11.8k
    PyObject *res;
298
11.8k
    int closed;
299
300
    /* Save the current exception, if any. */
301
11.8k
    PyObject *exc = PyErr_GetRaisedException();
302
303
    /* If `closed` doesn't exist or can't be evaluated as bool, then the
304
       object is probably in an unusable state, so ignore. */
305
11.8k
    if (PyObject_GetOptionalAttr(self, &_Py_ID(closed), &res) <= 0) {
306
0
        PyErr_Clear();
307
0
        closed = -1;
308
0
    }
309
11.8k
    else {
310
11.8k
        closed = PyObject_IsTrue(res);
311
11.8k
        Py_DECREF(res);
312
11.8k
        if (closed == -1)
313
0
            PyErr_Clear();
314
11.8k
    }
315
11.8k
    if (closed == 0) {
316
        /* Signal close() that it was called as part of the object
317
           finalization process. */
318
9.58k
        if (PyObject_SetAttr(self, &_Py_ID(_finalizing), Py_True))
319
0
            PyErr_Clear();
320
9.58k
        res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(close));
321
9.58k
        if (res == NULL) {
322
0
            PyErr_FormatUnraisable("Exception ignored "
323
0
                                   "while finalizing file %R", self);
324
0
        }
325
9.58k
        else {
326
9.58k
            Py_DECREF(res);
327
9.58k
        }
328
9.58k
    }
329
330
    /* Restore the saved exception. */
331
11.8k
    PyErr_SetRaisedException(exc);
332
11.8k
}
333
334
int
335
_PyIOBase_finalize(PyObject *self)
336
11.8k
{
337
11.8k
    int is_zombie;
338
339
    /* If _PyIOBase_finalize() is called from a destructor, we need to
340
       resurrect the object as calling close() can invoke arbitrary code. */
341
11.8k
    is_zombie = (Py_REFCNT(self) == 0);
342
11.8k
    if (is_zombie)
343
11.8k
        return PyObject_CallFinalizerFromDealloc(self);
344
0
    else {
345
0
        PyObject_CallFinalizer(self);
346
0
        return 0;
347
0
    }
348
11.8k
}
349
350
static int
351
iobase_traverse(PyObject *op, visitproc visit, void *arg)
352
2.77k
{
353
2.77k
    iobase *self = iobase_CAST(op);
354
2.77k
    Py_VISIT(Py_TYPE(self));
355
2.77k
    Py_VISIT(self->dict);
356
2.77k
    return 0;
357
2.77k
}
358
359
static int
360
iobase_clear(PyObject *op)
361
0
{
362
0
    iobase *self = iobase_CAST(op);
363
0
    Py_CLEAR(self->dict);
364
0
    return 0;
365
0
}
366
367
/* Destructor */
368
369
static void
370
iobase_dealloc(PyObject *op)
371
9.58k
{
372
    /* NOTE: since IOBaseObject has its own dict, Python-defined attributes
373
       are still available here for close() to use.
374
       However, if the derived class declares a __slots__, those slots are
375
       already gone.
376
    */
377
9.58k
    iobase *self = iobase_CAST(op);
378
9.58k
    if (_PyIOBase_finalize(op) < 0) {
379
        /* When called from a heap type's dealloc, the type will be
380
           decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */
381
0
        if (_PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) {
382
0
            Py_INCREF(Py_TYPE(self));
383
0
        }
384
0
        return;
385
0
    }
386
9.58k
    PyTypeObject *tp = Py_TYPE(self);
387
9.58k
    _PyObject_GC_UNTRACK(self);
388
9.58k
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
389
9.58k
    Py_CLEAR(self->dict);
390
9.58k
    tp->tp_free(self);
391
9.58k
    Py_DECREF(tp);
392
9.58k
}
393
394
/* Inquiry methods */
395
396
/*[clinic input]
397
_io._IOBase.seekable
398
399
Return whether object supports random access.
400
401
If False, seek(), tell() and truncate() will raise OSError.
402
This method may need to do a test seek().
403
[clinic start generated code]*/
404
405
static PyObject *
406
_io__IOBase_seekable_impl(PyObject *self)
407
/*[clinic end generated code: output=4c24c67f5f32a43d input=b976622f7fdf3063]*/
408
0
{
409
0
    Py_RETURN_FALSE;
410
0
}
411
412
PyObject *
413
_PyIOBase_check_seekable(_PyIO_State *state, PyObject *self, PyObject *args)
414
6
{
415
6
    PyObject *res  = PyObject_CallMethodNoArgs(self, &_Py_ID(seekable));
416
6
    if (res == NULL)
417
0
        return NULL;
418
6
    if (res != Py_True) {
419
0
        Py_CLEAR(res);
420
0
        iobase_unsupported(state, "File or stream is not seekable.");
421
0
        return NULL;
422
0
    }
423
6
    if (args == Py_True) {
424
6
        Py_DECREF(res);
425
6
    }
426
6
    return res;
427
6
}
428
429
/*[clinic input]
430
_io._IOBase.readable
431
432
Return whether object was opened for reading.
433
434
If False, read() will raise OSError.
435
[clinic start generated code]*/
436
437
static PyObject *
438
_io__IOBase_readable_impl(PyObject *self)
439
/*[clinic end generated code: output=e48089250686388b input=285b3b866a0ec35f]*/
440
32
{
441
32
    Py_RETURN_FALSE;
442
32
}
443
444
/* May be called with any object */
445
PyObject *
446
_PyIOBase_check_readable(_PyIO_State *state, PyObject *self, PyObject *args)
447
1.02k
{
448
1.02k
    PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(readable));
449
1.02k
    if (res == NULL)
450
0
        return NULL;
451
1.02k
    if (res != Py_True) {
452
0
        Py_CLEAR(res);
453
0
        iobase_unsupported(state, "File or stream is not readable.");
454
0
        return NULL;
455
0
    }
456
1.02k
    if (args == Py_True) {
457
1.02k
        Py_DECREF(res);
458
1.02k
    }
459
1.02k
    return res;
460
1.02k
}
461
462
/*[clinic input]
463
_io._IOBase.writable
464
465
Return whether object was opened for writing.
466
467
If False, write() will raise OSError.
468
[clinic start generated code]*/
469
470
static PyObject *
471
_io__IOBase_writable_impl(PyObject *self)
472
/*[clinic end generated code: output=406001d0985be14f input=9dcac18a013a05b5]*/
473
16
{
474
16
    Py_RETURN_FALSE;
475
16
}
476
477
/* May be called with any object */
478
PyObject *
479
_PyIOBase_check_writable(_PyIO_State *state, PyObject *self, PyObject *args)
480
32
{
481
32
    PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(writable));
482
32
    if (res == NULL)
483
0
        return NULL;
484
32
    if (res != Py_True) {
485
0
        Py_CLEAR(res);
486
0
        iobase_unsupported(state, "File or stream is not writable.");
487
0
        return NULL;
488
0
    }
489
32
    if (args == Py_True) {
490
32
        Py_DECREF(res);
491
32
    }
492
32
    return res;
493
32
}
494
495
/* Context manager */
496
497
static PyObject *
498
iobase_enter(PyObject *self, PyObject *args)
499
1.24k
{
500
1.24k
    if (iobase_check_closed(self))
501
0
        return NULL;
502
503
1.24k
    return Py_NewRef(self);
504
1.24k
}
505
506
static PyObject *
507
iobase_exit(PyObject *self, PyObject *args)
508
1.24k
{
509
1.24k
    return PyObject_CallMethodNoArgs(self, &_Py_ID(close));
510
1.24k
}
511
512
/* Lower-level APIs */
513
514
/* XXX Should these be present even if unimplemented? */
515
516
/*[clinic input]
517
_io._IOBase.fileno
518
    cls: defining_class
519
    /
520
521
Return underlying file descriptor if one exists.
522
523
Raise OSError if the IO object does not use a file descriptor.
524
[clinic start generated code]*/
525
526
static PyObject *
527
_io__IOBase_fileno_impl(PyObject *self, PyTypeObject *cls)
528
/*[clinic end generated code: output=7caaa32a6f4ada3d input=1927c8bea5c85099]*/
529
0
{
530
0
    _PyIO_State *state = get_io_state_by_cls(cls);
531
0
    return iobase_unsupported(state, "fileno");
532
0
}
533
534
/*[clinic input]
535
_io._IOBase.isatty
536
537
Return whether this is an 'interactive' stream.
538
539
Return False if it can't be determined.
540
[clinic start generated code]*/
541
542
static PyObject *
543
_io__IOBase_isatty_impl(PyObject *self)
544
/*[clinic end generated code: output=60cab77cede41cdd input=9ef76530d368458b]*/
545
0
{
546
0
    if (iobase_check_closed(self))
547
0
        return NULL;
548
0
    Py_RETURN_FALSE;
549
0
}
550
551
/* Readline(s) and writelines */
552
553
/*[clinic input]
554
_io._IOBase.readline
555
    size as limit: Py_ssize_t(accept={int, NoneType}) = -1
556
    /
557
558
Read and return a line from the stream.
559
560
If size is specified, at most size bytes will be read.
561
562
The line terminator is always b'\n' for binary files; for text
563
files, the newlines argument to open can be used to select the line
564
terminator(s) recognized.
565
[clinic start generated code]*/
566
567
static PyObject *
568
_io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit)
569
/*[clinic end generated code: output=4479f79b58187840 input=d0c596794e877bff]*/
570
0
{
571
    /* For backwards compatibility, a (slowish) readline(). */
572
573
0
    PyObject *peek, *buffer, *result;
574
0
    Py_ssize_t old_size = -1;
575
576
0
    if (PyObject_GetOptionalAttr(self, &_Py_ID(peek), &peek) < 0) {
577
0
        return NULL;
578
0
    }
579
580
0
    buffer = PyByteArray_FromStringAndSize(NULL, 0);
581
0
    if (buffer == NULL) {
582
0
        Py_XDECREF(peek);
583
0
        return NULL;
584
0
    }
585
586
0
    while (limit < 0 || PyByteArray_GET_SIZE(buffer) < limit) {
587
0
        Py_ssize_t nreadahead = 1;
588
0
        PyObject *b;
589
590
0
        if (peek != NULL) {
591
0
            PyObject *readahead = PyObject_CallOneArg(peek, _PyLong_GetOne());
592
0
            if (readahead == NULL) {
593
                /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
594
                   when EINTR occurs so we needn't do it ourselves. */
595
0
                if (_PyIO_trap_eintr()) {
596
0
                    continue;
597
0
                }
598
0
                goto fail;
599
0
            }
600
0
            if (!PyBytes_Check(readahead)) {
601
0
                PyErr_Format(PyExc_OSError,
602
0
                             "peek() should have returned a bytes object, "
603
0
                             "not '%.200s'", Py_TYPE(readahead)->tp_name);
604
0
                Py_DECREF(readahead);
605
0
                goto fail;
606
0
            }
607
0
            if (PyBytes_GET_SIZE(readahead) > 0) {
608
0
                Py_ssize_t n = 0;
609
0
                const char *buf = PyBytes_AS_STRING(readahead);
610
0
                if (limit >= 0) {
611
0
                    do {
612
0
                        if (n >= PyBytes_GET_SIZE(readahead) || n >= limit)
613
0
                            break;
614
0
                        if (buf[n++] == '\n')
615
0
                            break;
616
0
                    } while (1);
617
0
                }
618
0
                else {
619
0
                    do {
620
0
                        if (n >= PyBytes_GET_SIZE(readahead))
621
0
                            break;
622
0
                        if (buf[n++] == '\n')
623
0
                            break;
624
0
                    } while (1);
625
0
                }
626
0
                nreadahead = n;
627
0
            }
628
0
            Py_DECREF(readahead);
629
0
        }
630
631
0
        b = _PyObject_CallMethod(self, &_Py_ID(read), "n", nreadahead);
632
0
        if (b == NULL) {
633
            /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
634
               when EINTR occurs so we needn't do it ourselves. */
635
0
            if (_PyIO_trap_eintr()) {
636
0
                continue;
637
0
            }
638
0
            goto fail;
639
0
        }
640
0
        if (!PyBytes_Check(b)) {
641
0
            PyErr_Format(PyExc_OSError,
642
0
                         "read() should have returned a bytes object, "
643
0
                         "not '%.200s'", Py_TYPE(b)->tp_name);
644
0
            Py_DECREF(b);
645
0
            goto fail;
646
0
        }
647
0
        if (PyBytes_GET_SIZE(b) == 0) {
648
0
            Py_DECREF(b);
649
0
            break;
650
0
        }
651
652
0
        old_size = PyByteArray_GET_SIZE(buffer);
653
0
        if (PyByteArray_Resize(buffer, old_size + PyBytes_GET_SIZE(b)) < 0) {
654
0
            Py_DECREF(b);
655
0
            goto fail;
656
0
        }
657
0
        memcpy(PyByteArray_AS_STRING(buffer) + old_size,
658
0
               PyBytes_AS_STRING(b), PyBytes_GET_SIZE(b));
659
660
0
        Py_DECREF(b);
661
662
0
        if (PyByteArray_AS_STRING(buffer)[PyByteArray_GET_SIZE(buffer) - 1] == '\n')
663
0
            break;
664
0
    }
665
666
0
    result = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(buffer),
667
0
                                       PyByteArray_GET_SIZE(buffer));
668
0
    Py_XDECREF(peek);
669
0
    Py_DECREF(buffer);
670
0
    return result;
671
0
  fail:
672
0
    Py_XDECREF(peek);
673
0
    Py_DECREF(buffer);
674
0
    return NULL;
675
0
}
676
677
static PyObject *
678
iobase_iter(PyObject *self)
679
39.4k
{
680
39.4k
    if (iobase_check_closed(self))
681
0
        return NULL;
682
683
39.4k
    return Py_NewRef(self);
684
39.4k
}
685
686
static PyObject *
687
iobase_iternext(PyObject *self)
688
0
{
689
0
    PyObject *line = PyObject_CallMethodNoArgs(self, &_Py_ID(readline));
690
691
0
    if (line == NULL)
692
0
        return NULL;
693
694
0
    if (PyObject_Size(line) <= 0) {
695
        /* Error or empty */
696
0
        Py_DECREF(line);
697
0
        return NULL;
698
0
    }
699
700
0
    return line;
701
0
}
702
703
/*[clinic input]
704
_io._IOBase.readlines
705
    hint: Py_ssize_t(accept={int, NoneType}) = -1
706
    /
707
708
Return a list of lines from the stream.
709
710
hint can be specified to control the number of lines read: no more
711
lines will be read if the total size (in bytes/characters) of all
712
lines so far exceeds hint.
713
[clinic start generated code]*/
714
715
static PyObject *
716
_io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint)
717
/*[clinic end generated code: output=2f50421677fa3dea input=9400c786ea9dc416]*/
718
39.4k
{
719
39.4k
    Py_ssize_t length = 0;
720
39.4k
    PyObject *result, *it = NULL;
721
722
39.4k
    result = PyList_New(0);
723
39.4k
    if (result == NULL)
724
0
        return NULL;
725
726
39.4k
    if (hint <= 0) {
727
        /* XXX special-casing this made sense in the Python version in order
728
           to remove the bytecode interpretation overhead, but it could
729
           probably be removed here. */
730
39.4k
        PyObject *ret = PyObject_CallMethodObjArgs(result, &_Py_ID(extend),
731
39.4k
                                                   self, NULL);
732
39.4k
        if (ret == NULL) {
733
0
            goto error;
734
0
        }
735
39.4k
        Py_DECREF(ret);
736
39.4k
        return result;
737
39.4k
    }
738
739
0
    it = PyObject_GetIter(self);
740
0
    if (it == NULL) {
741
0
        goto error;
742
0
    }
743
744
0
    while (1) {
745
0
        Py_ssize_t line_length;
746
0
        PyObject *line = PyIter_Next(it);
747
0
        if (line == NULL) {
748
0
            if (PyErr_Occurred()) {
749
0
                goto error;
750
0
            }
751
0
            else
752
0
                break; /* StopIteration raised */
753
0
        }
754
755
0
        if (PyList_Append(result, line) < 0) {
756
0
            Py_DECREF(line);
757
0
            goto error;
758
0
        }
759
0
        line_length = PyObject_Size(line);
760
0
        Py_DECREF(line);
761
0
        if (line_length < 0) {
762
0
            goto error;
763
0
        }
764
0
        if (line_length > hint - length)
765
0
            break;
766
0
        length += line_length;
767
0
    }
768
769
0
    Py_DECREF(it);
770
0
    return result;
771
772
0
 error:
773
0
    Py_XDECREF(it);
774
0
    Py_DECREF(result);
775
0
    return NULL;
776
0
}
777
778
/*[clinic input]
779
_io._IOBase.writelines
780
    lines: object
781
    /
782
783
Write a list of lines to stream.
784
785
Line separators are not added, so it is usual for each of the
786
lines provided to have a line separator at the end.
787
[clinic start generated code]*/
788
789
static PyObject *
790
_io__IOBase_writelines(PyObject *self, PyObject *lines)
791
/*[clinic end generated code: output=976eb0a9b60a6628 input=cac3fc8864183359]*/
792
0
{
793
0
    PyObject *iter, *res;
794
795
0
    if (iobase_check_closed(self))
796
0
        return NULL;
797
798
0
    iter = PyObject_GetIter(lines);
799
0
    if (iter == NULL)
800
0
        return NULL;
801
802
0
    while (1) {
803
0
        PyObject *line = PyIter_Next(iter);
804
0
        if (line == NULL) {
805
0
            if (PyErr_Occurred()) {
806
0
                Py_DECREF(iter);
807
0
                return NULL;
808
0
            }
809
0
            else
810
0
                break; /* Stop Iteration */
811
0
        }
812
813
0
        res = NULL;
814
0
        do {
815
0
            res = PyObject_CallMethodObjArgs(self, &_Py_ID(write), line, NULL);
816
0
        } while (res == NULL && _PyIO_trap_eintr());
817
0
        Py_DECREF(line);
818
0
        if (res == NULL) {
819
0
            Py_DECREF(iter);
820
0
            return NULL;
821
0
        }
822
0
        Py_DECREF(res);
823
0
    }
824
0
    Py_DECREF(iter);
825
0
    Py_RETURN_NONE;
826
0
}
827
828
#define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
829
#include "clinic/iobase.c.h"
830
#undef clinic_state
831
832
static PyMethodDef iobase_methods[] = {
833
    _IO__IOBASE_SEEK_METHODDEF
834
    _IO__IOBASE_TELL_METHODDEF
835
    _IO__IOBASE_TRUNCATE_METHODDEF
836
    _IO__IOBASE_FLUSH_METHODDEF
837
    _IO__IOBASE_CLOSE_METHODDEF
838
839
    _IO__IOBASE_SEEKABLE_METHODDEF
840
    _IO__IOBASE_READABLE_METHODDEF
841
    _IO__IOBASE_WRITABLE_METHODDEF
842
843
    {"_checkClosed",   _PyIOBase_check_closed, METH_NOARGS},
844
    {"_checkSeekable", iobase_check_seekable, METH_NOARGS},
845
    {"_checkReadable", iobase_check_readable, METH_NOARGS},
846
    {"_checkWritable", iobase_check_writable, METH_NOARGS},
847
848
    _IO__IOBASE_FILENO_METHODDEF
849
    _IO__IOBASE_ISATTY_METHODDEF
850
851
    {"__enter__", iobase_enter, METH_NOARGS},
852
    {"__exit__", iobase_exit, METH_VARARGS},
853
854
    _IO__IOBASE_READLINE_METHODDEF
855
    _IO__IOBASE_READLINES_METHODDEF
856
    _IO__IOBASE_WRITELINES_METHODDEF
857
858
    {NULL, NULL}
859
};
860
861
static PyGetSetDef iobase_getset[] = {
862
    {"__dict__", PyObject_GenericGetDict, NULL, NULL},
863
    {"closed", iobase_closed_get, NULL, NULL},
864
    {NULL}
865
};
866
867
static struct PyMemberDef iobase_members[] = {
868
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(iobase, weakreflist), Py_READONLY},
869
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(iobase, dict), Py_READONLY},
870
    {NULL},
871
};
872
873
874
static PyType_Slot iobase_slots[] = {
875
    {Py_tp_dealloc, iobase_dealloc},
876
    {Py_tp_doc, (void *)iobase_doc},
877
    {Py_tp_traverse, iobase_traverse},
878
    {Py_tp_clear, iobase_clear},
879
    {Py_tp_iter, iobase_iter},
880
    {Py_tp_iternext, iobase_iternext},
881
    {Py_tp_methods, iobase_methods},
882
    {Py_tp_members, iobase_members},
883
    {Py_tp_getset, iobase_getset},
884
    {Py_tp_finalize, iobase_finalize},
885
    {0, NULL},
886
};
887
888
PyType_Spec iobase_spec = {
889
    .name = "_io._IOBase",
890
    .basicsize = sizeof(iobase),
891
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
892
              Py_TPFLAGS_IMMUTABLETYPE),
893
    .slots = iobase_slots,
894
};
895
896
/*
897
 * RawIOBase class, Inherits from IOBase.
898
 */
899
PyDoc_STRVAR(rawiobase_doc,
900
             "Base class for raw binary I/O.");
901
902
/*
903
 * The read() method is implemented by calling readinto(); derived classes
904
 * that want to support read() only need to implement readinto() as a
905
 * primitive operation.  In general, readinto() can be more efficient than
906
 * read().
907
 *
908
 * (It would be tempting to also provide an implementation of readinto() in
909
 * terms of read(), in case the latter is a more suitable primitive operation,
910
 * but that would lead to nasty recursion in case a subclass doesn't implement
911
 * either.)
912
*/
913
914
/*[clinic input]
915
_io._RawIOBase.read
916
    size as n: Py_ssize_t = -1
917
    /
918
[clinic start generated code]*/
919
920
static PyObject *
921
_io__RawIOBase_read_impl(PyObject *self, Py_ssize_t n)
922
/*[clinic end generated code: output=6cdeb731e3c9f13c input=b6d0dcf6417d1374]*/
923
0
{
924
0
    PyObject *b, *res;
925
926
0
    if (n < 0) {
927
0
        return PyObject_CallMethodNoArgs(self, &_Py_ID(readall));
928
0
    }
929
930
    /* TODO: allocate a bytes object directly instead and manually construct
931
       a writable memoryview pointing to it. */
932
0
    b = PyByteArray_FromStringAndSize(NULL, n);
933
0
    if (b == NULL)
934
0
        return NULL;
935
936
0
    res = PyObject_CallMethodObjArgs(self, &_Py_ID(readinto), b, NULL);
937
0
    if (res == NULL || res == Py_None) {
938
0
        Py_DECREF(b);
939
0
        return res;
940
0
    }
941
942
0
    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
943
0
    Py_DECREF(res);
944
0
    if (n == -1 && PyErr_Occurred()) {
945
0
        Py_DECREF(b);
946
0
        return NULL;
947
0
    }
948
949
0
    res = PyBytes_FromStringAndSize(PyByteArray_AsString(b), n);
950
0
    Py_DECREF(b);
951
0
    return res;
952
0
}
953
954
955
/*[clinic input]
956
_io._RawIOBase.readall
957
958
Read until EOF, using multiple read() call.
959
[clinic start generated code]*/
960
961
static PyObject *
962
_io__RawIOBase_readall_impl(PyObject *self)
963
/*[clinic end generated code: output=1987b9ce929425a0 input=688874141213622a]*/
964
0
{
965
0
    int r;
966
0
    PyObject *chunks = PyList_New(0);
967
0
    PyObject *result;
968
969
0
    if (chunks == NULL)
970
0
        return NULL;
971
972
0
    while (1) {
973
0
        PyObject *data = _PyObject_CallMethod(self, &_Py_ID(read),
974
0
                                              "i", DEFAULT_BUFFER_SIZE);
975
0
        if (!data) {
976
            /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
977
               when EINTR occurs so we needn't do it ourselves. */
978
0
            if (_PyIO_trap_eintr()) {
979
0
                continue;
980
0
            }
981
0
            Py_DECREF(chunks);
982
0
            return NULL;
983
0
        }
984
0
        if (data == Py_None) {
985
0
            if (PyList_GET_SIZE(chunks) == 0) {
986
0
                Py_DECREF(chunks);
987
0
                return data;
988
0
            }
989
0
            Py_DECREF(data);
990
0
            break;
991
0
        }
992
0
        if (!PyBytes_Check(data)) {
993
0
            Py_DECREF(chunks);
994
0
            Py_DECREF(data);
995
0
            PyErr_SetString(PyExc_TypeError, "read() should return bytes");
996
0
            return NULL;
997
0
        }
998
0
        if (PyBytes_GET_SIZE(data) == 0) {
999
            /* EOF */
1000
0
            Py_DECREF(data);
1001
0
            break;
1002
0
        }
1003
0
        r = PyList_Append(chunks, data);
1004
0
        Py_DECREF(data);
1005
0
        if (r < 0) {
1006
0
            Py_DECREF(chunks);
1007
0
            return NULL;
1008
0
        }
1009
0
    }
1010
0
    result = PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks);
1011
0
    Py_DECREF(chunks);
1012
0
    return result;
1013
0
}
1014
1015
static PyObject *
1016
rawiobase_readinto(PyObject *self, PyObject *args)
1017
0
{
1018
0
    PyErr_SetNone(PyExc_NotImplementedError);
1019
0
    return NULL;
1020
0
}
1021
1022
static PyObject *
1023
rawiobase_write(PyObject *self, PyObject *args)
1024
0
{
1025
0
    PyErr_SetNone(PyExc_NotImplementedError);
1026
0
    return NULL;
1027
0
}
1028
1029
static PyMethodDef rawiobase_methods[] = {
1030
    _IO__RAWIOBASE_READ_METHODDEF
1031
    _IO__RAWIOBASE_READALL_METHODDEF
1032
    {"readinto", rawiobase_readinto, METH_VARARGS},
1033
    {"write", rawiobase_write, METH_VARARGS},
1034
    {NULL, NULL}
1035
};
1036
1037
static PyType_Slot rawiobase_slots[] = {
1038
    {Py_tp_doc, (void *)rawiobase_doc},
1039
    {Py_tp_methods, rawiobase_methods},
1040
    {0, NULL},
1041
};
1042
1043
/* Do not set Py_TPFLAGS_HAVE_GC so that tp_traverse and tp_clear are inherited */
1044
PyType_Spec rawiobase_spec = {
1045
    .name = "_io._RawIOBase",
1046
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1047
              Py_TPFLAGS_IMMUTABLETYPE),
1048
    .slots = rawiobase_slots,
1049
};