Skip to content

Commit 13185f2

Browse files
cmaloneymiss-islington
authored andcommitted
gh-160427: Return None from TextIOWrapper.buffer when detached (GH-160802)
gh-154523 turned the buffer member descriptor into a getter that raises ValueError when the buffer is NULL, and the backport shipped in 3.14.9 and 3.15.1. That made hasattr(stream, "buffer") raise after detach(). Restore the old member descriptor result (None) while keeping the critical section. (cherry picked from commit 3422197) Co-authored-by: Cody Maloney <cmaloney@users.noreply.github.com>
1 parent 04c7edf commit 13185f2

3 files changed

Lines changed: 10 additions & 4 deletions

File tree

‎Lib/test/test_io/test_textio.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ def test_detach(self):
243243
r = self.BytesIO()
244244
b = self.BufferedWriter(r)
245245
t = self.TextIOWrapper(b, encoding="ascii")
246+
self.assertIs(t.buffer, b)
246247
self.assertIs(t.detach(), b)
247248

248249
t = self.TextIOWrapper(b, encoding="ascii")
@@ -258,6 +259,7 @@ def test_detach(self):
258259
self.assertEqual(t.errors, "strict")
259260
self.assertFalse(t.line_buffering)
260261
self.assertFalse(t.write_through)
262+
self.assertIsNone(t.buffer)
261263

262264
def test_repr(self):
263265
raw = self.BytesIO("hello".encode("utf-8"))
@@ -1713,9 +1715,7 @@ def readinto(self, b):
17131715
self.BufferedReader(raw), encoding="utf-8")
17141716
method = getattr(wrapper, method_name)
17151717
self.assertEqual(method(), "ab\n")
1716-
with self.assertRaisesRegex(ValueError,
1717-
"underlying buffer has been detached"):
1718-
getattr(wrapper, 'buffer')
1718+
self.assertIsNone(wrapper.buffer)
17191719

17201720

17211721
class PyTextIOWrapperTest(TextIOWrapperTest, PyTestCase):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :attr:`~io.TextIOBase.buffer` of a detached :class:`io.TextIOWrapper`
2+
raising :exc:`ValueError` instead of returning ``None``.

‎Modules/_io/textio.c‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3453,7 +3453,11 @@ static PyObject *
34533453
_io_TextIOWrapper_buffer_get_impl(textio *self)
34543454
/*[clinic end generated code: output=d265a34555aa5d4b input=5951cfa148f7350a]*/
34553455
{
3456-
return buffer_access_safe(self);
3456+
/* gh-160427: None once detached, matching the former member descriptor. */
3457+
if (self->buffer == NULL) {
3458+
Py_RETURN_NONE;
3459+
}
3460+
return Py_NewRef(self->buffer);
34573461
}
34583462

34593463
static PyMethodDef incrementalnewlinedecoder_methods[] = {

0 commit comments

Comments
 (0)