https://github.com/python/cpython/commit/4af98bdb94beb37453a33b989f8ef466f8ef0e21 commit: 4af98bdb94beb37453a33b989f8ef466f8ef0e21 branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: cmaloney <[email protected]> date: 2026-11-05T14:29:49-08:00 summary:
[3.15] gh-160427: Return None from TextIOWrapper.buffer when detached (GH-160802) (#161449) 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 3422197f5481ac1b3134e2633332415a02959ba4) Co-authored-by: Cody Maloney <[email protected]> files: A Misc/NEWS.d/next/Library/2026-10-26-16-15-29.gh-issue-160427.9G4EBb.rst M Lib/test/test_io/test_textio.py M Modules/_io/textio.c diff --git a/Lib/test/test_io/test_textio.py b/Lib/test/test_io/test_textio.py index d252514039a6cb..185a4ef0b4c56f 100644 --- a/Lib/test/test_io/test_textio.py +++ b/Lib/test/test_io/test_textio.py @@ -243,6 +243,7 @@ def test_detach(self): r = self.BytesIO() b = self.BufferedWriter(r) t = self.TextIOWrapper(b, encoding="ascii") + self.assertIs(t.buffer, b) self.assertIs(t.detach(), b) t = self.TextIOWrapper(b, encoding="ascii") @@ -258,6 +259,7 @@ def test_detach(self): self.assertEqual(t.errors, "strict") self.assertFalse(t.line_buffering) self.assertFalse(t.write_through) + self.assertIsNone(t.buffer) def test_repr(self): raw = self.BytesIO("hello".encode("utf-8")) @@ -1713,9 +1715,7 @@ def readinto(self, b): self.BufferedReader(raw), encoding="utf-8") method = getattr(wrapper, method_name) self.assertEqual(method(), "ab\n") - with self.assertRaisesRegex(ValueError, - "underlying buffer has been detached"): - getattr(wrapper, 'buffer') + self.assertIsNone(wrapper.buffer) class PyTextIOWrapperTest(TextIOWrapperTest, PyTestCase): diff --git a/Misc/NEWS.d/next/Library/2026-10-26-16-15-29.gh-issue-160427.9G4EBb.rst b/Misc/NEWS.d/next/Library/2026-10-26-16-15-29.gh-issue-160427.9G4EBb.rst new file mode 100644 index 00000000000000..d57dd02a6d576f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-26-16-15-29.gh-issue-160427.9G4EBb.rst @@ -0,0 +1,2 @@ +Fix :attr:`~io.TextIOBase.buffer` of a detached :class:`io.TextIOWrapper` +raising :exc:`ValueError` instead of returning ``None``. diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index a8e7bef0283f8e..6641d12848be59 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -3453,7 +3453,11 @@ static PyObject * _io_TextIOWrapper_buffer_get_impl(textio *self) /*[clinic end generated code: output=d265a34555aa5d4b input=5951cfa148f7350a]*/ { - return buffer_access_safe(self); + /* gh-160427: None once detached, matching the former member descriptor. */ + if (self->buffer == NULL) { + Py_RETURN_NONE; + } + return Py_NewRef(self->buffer); } static PyMethodDef incrementalnewlinedecoder_methods[] = { _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
