@@ -68,11 +68,9 @@ PyDoc_STRVAR(iobase_doc,
68
68
by whatever subclass. */
69
69
70
70
_Py_IDENTIFIER (__IOBase_closed );
71
- #define IS_CLOSED (self ) \
72
- _PyObject_HasAttrId(self, &PyId___IOBase_closed)
73
-
74
71
_Py_IDENTIFIER (read );
75
72
73
+
76
74
/* Internal methods */
77
75
static PyObject *
78
76
iobase_unsupported (const char * message )
@@ -131,6 +129,24 @@ iobase_truncate(PyObject *self, PyObject *args)
131
129
return iobase_unsupported ("truncate" );
132
130
}
133
131
132
+ static int
133
+ iobase_is_closed (PyObject * self )
134
+ {
135
+ PyObject * res ;
136
+ /* This gets the derived attribute, which is *not* __IOBase_closed
137
+ in most cases! */
138
+ res = _PyObject_GetAttrId (self , & PyId___IOBase_closed );
139
+ if (res == NULL ) {
140
+ if (!PyErr_ExceptionMatches (PyExc_AttributeError )) {
141
+ return -1 ;
142
+ }
143
+ PyErr_Clear ();
144
+ return 0 ;
145
+ }
146
+ Py_DECREF (res );
147
+ return 1 ;
148
+ }
149
+
134
150
/* Flush and close methods */
135
151
136
152
/*[clinic input]
@@ -146,45 +162,60 @@ _io__IOBase_flush_impl(PyObject *self)
146
162
/*[clinic end generated code: output=7cef4b4d54656a3b input=773be121abe270aa]*/
147
163
{
148
164
/* XXX Should this return the number of bytes written??? */
149
- if (IS_CLOSED (self )) {
165
+ int closed = iobase_is_closed (self );
166
+
167
+ if (!closed ) {
168
+ Py_RETURN_NONE ;
169
+ }
170
+ if (closed > 0 ) {
150
171
PyErr_SetString (PyExc_ValueError , "I/O operation on closed file." );
172
+ }
173
+ return NULL ;
174
+ }
175
+
176
+ static PyObject *
177
+ iobase_closed_get (PyObject * self , void * context )
178
+ {
179
+ int closed = iobase_is_closed (self );
180
+ if (closed < 0 ) {
151
181
return NULL ;
152
182
}
153
- Py_RETURN_NONE ;
183
+ return PyBool_FromLong ( closed ) ;
154
184
}
155
185
156
186
static int
157
- iobase_closed (PyObject * self )
187
+ iobase_check_closed (PyObject * self )
158
188
{
159
189
PyObject * res ;
160
190
int closed ;
161
191
/* This gets the derived attribute, which is *not* __IOBase_closed
162
192
in most cases! */
163
- res = PyObject_GetAttr (self , _PyIO_str_closed );
164
- if (res == NULL )
193
+ res = _PyObject_GetAttrWithoutError (self , _PyIO_str_closed );
194
+ if (res == NULL ) {
195
+ if (PyErr_Occurred ()) {
196
+ return -1 ;
197
+ }
165
198
return 0 ;
199
+ }
166
200
closed = PyObject_IsTrue (res );
167
201
Py_DECREF (res );
168
- return closed ;
169
- }
170
-
171
- static PyObject *
172
- iobase_closed_get (PyObject * self , void * context )
173
- {
174
- return PyBool_FromLong (IS_CLOSED (self ));
202
+ if (closed <= 0 ) {
203
+ return closed ;
204
+ }
205
+ PyErr_SetString (PyExc_ValueError , "I/O operation on closed file." );
206
+ return -1 ;
175
207
}
176
208
177
209
PyObject *
178
210
_PyIOBase_check_closed (PyObject * self , PyObject * args )
179
211
{
180
- if (iobase_closed (self )) {
181
- PyErr_SetString (PyExc_ValueError , "I/O operation on closed file." );
212
+ if (iobase_check_closed (self )) {
182
213
return NULL ;
183
214
}
184
- if (args == Py_True )
215
+ if (args == Py_True ) {
185
216
return Py_None ;
186
- else
187
- Py_RETURN_NONE ;
217
+ }
218
+ Py_RETURN_NONE ;
188
219
}
189
220
190
221
/* XXX: IOBase thinks it has to maintain its own internal state in
@@ -204,9 +235,14 @@ _io__IOBase_close_impl(PyObject *self)
204
235
/*[clinic end generated code: output=63c6a6f57d783d6d input=f4494d5c31dbc6b7]*/
205
236
{
206
237
PyObject * res ;
238
+ int closed = iobase_is_closed (self );
207
239
208
- if (IS_CLOSED (self ))
240
+ if (closed < 0 ) {
241
+ return NULL ;
242
+ }
243
+ if (closed ) {
209
244
Py_RETURN_NONE ;
245
+ }
210
246
211
247
res = PyObject_CallMethodObjArgs (self , _PyIO_str_flush , NULL );
212
248
@@ -237,7 +273,7 @@ iobase_finalize(PyObject *self)
237
273
238
274
/* If `closed` doesn't exist or can't be evaluated as bool, then the
239
275
object is probably in an unusable state, so ignore. */
240
- res = PyObject_GetAttr (self , _PyIO_str_closed );
276
+ res = _PyObject_GetAttrWithoutError (self , _PyIO_str_closed );
241
277
if (res == NULL ) {
242
278
PyErr_Clear ();
243
279
closed = -1 ;
@@ -428,7 +464,7 @@ _PyIOBase_check_writable(PyObject *self, PyObject *args)
428
464
static PyObject *
429
465
iobase_enter (PyObject * self , PyObject * args )
430
466
{
431
- if (_PyIOBase_check_closed (self , Py_True ) == NULL )
467
+ if (iobase_check_closed (self ) )
432
468
return NULL ;
433
469
434
470
Py_INCREF (self );
@@ -472,7 +508,7 @@ static PyObject *
472
508
_io__IOBase_isatty_impl (PyObject * self )
473
509
/*[clinic end generated code: output=60cab77cede41cdd input=9ef76530d368458b]*/
474
510
{
475
- if (_PyIOBase_check_closed (self , Py_True ) == NULL )
511
+ if (iobase_check_closed (self ) )
476
512
return NULL ;
477
513
Py_RETURN_FALSE ;
478
514
}
@@ -499,24 +535,26 @@ _io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit)
499
535
{
500
536
/* For backwards compatibility, a (slowish) readline(). */
501
537
502
- int has_peek = 0 ;
503
- PyObject * buffer , * result ;
538
+ PyObject * peek , * buffer , * result ;
504
539
Py_ssize_t old_size = -1 ;
505
- _Py_IDENTIFIER (peek );
506
540
507
- if (_PyObject_HasAttrId (self , & PyId_peek ))
508
- has_peek = 1 ;
541
+ peek = _PyObject_GetAttrWithoutError (self , _PyIO_str_peek );
542
+ if (peek == NULL && PyErr_Occurred ()) {
543
+ return NULL ;
544
+ }
509
545
510
546
buffer = PyByteArray_FromStringAndSize (NULL , 0 );
511
- if (buffer == NULL )
547
+ if (buffer == NULL ) {
548
+ Py_XDECREF (peek );
512
549
return NULL ;
550
+ }
513
551
514
552
while (limit < 0 || PyByteArray_GET_SIZE (buffer ) < limit ) {
515
553
Py_ssize_t nreadahead = 1 ;
516
554
PyObject * b ;
517
555
518
- if (has_peek ) {
519
- PyObject * readahead = _PyObject_CallMethodId ( self , & PyId_peek , "i" , 1 );
556
+ if (peek != NULL ) {
557
+ PyObject * readahead = PyObject_CallFunctionObjArgs ( peek , _PyLong_One , NULL );
520
558
if (readahead == NULL ) {
521
559
/* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
522
560
when EINTR occurs so we needn't do it ourselves. */
@@ -593,17 +631,19 @@ _io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit)
593
631
594
632
result = PyBytes_FromStringAndSize (PyByteArray_AS_STRING (buffer ),
595
633
PyByteArray_GET_SIZE (buffer ));
634
+ Py_XDECREF (peek );
596
635
Py_DECREF (buffer );
597
636
return result ;
598
637
fail :
638
+ Py_XDECREF (peek );
599
639
Py_DECREF (buffer );
600
640
return NULL ;
601
641
}
602
642
603
643
static PyObject *
604
644
iobase_iter (PyObject * self )
605
645
{
606
- if (_PyIOBase_check_closed (self , Py_True ) == NULL )
646
+ if (iobase_check_closed (self ) )
607
647
return NULL ;
608
648
609
649
Py_INCREF (self );
@@ -716,7 +756,7 @@ _io__IOBase_writelines(PyObject *self, PyObject *lines)
716
756
{
717
757
PyObject * iter , * res ;
718
758
719
- if (_PyIOBase_check_closed (self , Py_True ) == NULL )
759
+ if (iobase_check_closed (self ) )
720
760
return NULL ;
721
761
722
762
iter = PyObject_GetIter (lines );
0 commit comments