Commit 7f8f4180 authored by Antoine Pitrou's avatar Antoine Pitrou

Issue #10750: The `raw` attribute of buffered IO objects is now read-only.

parent cfee0e83
...@@ -676,7 +676,7 @@ class _BufferedIOMixin(BufferedIOBase): ...@@ -676,7 +676,7 @@ class _BufferedIOMixin(BufferedIOBase):
""" """
def __init__(self, raw): def __init__(self, raw):
self.raw = raw self._raw = raw
### Positioning ### ### Positioning ###
...@@ -720,8 +720,8 @@ class _BufferedIOMixin(BufferedIOBase): ...@@ -720,8 +720,8 @@ class _BufferedIOMixin(BufferedIOBase):
if self.raw is None: if self.raw is None:
raise ValueError("raw stream already detached") raise ValueError("raw stream already detached")
self.flush() self.flush()
raw = self.raw raw = self._raw
self.raw = None self._raw = None
return raw return raw
### Inquiries ### ### Inquiries ###
...@@ -735,6 +735,10 @@ class _BufferedIOMixin(BufferedIOBase): ...@@ -735,6 +735,10 @@ class _BufferedIOMixin(BufferedIOBase):
def writable(self): def writable(self):
return self.raw.writable() return self.raw.writable()
@property
def raw(self):
return self._raw
@property @property
def closed(self): def closed(self):
return self.raw.closed return self.raw.closed
...@@ -1465,7 +1469,7 @@ class TextIOWrapper(TextIOBase): ...@@ -1465,7 +1469,7 @@ class TextIOWrapper(TextIOBase):
if not isinstance(errors, str): if not isinstance(errors, str):
raise ValueError("invalid errors: %r" % errors) raise ValueError("invalid errors: %r" % errors)
self.buffer = buffer self._buffer = buffer
self._line_buffering = line_buffering self._line_buffering = line_buffering
self._encoding = encoding self._encoding = encoding
self._errors = errors self._errors = errors
...@@ -1520,6 +1524,10 @@ class TextIOWrapper(TextIOBase): ...@@ -1520,6 +1524,10 @@ class TextIOWrapper(TextIOBase):
def line_buffering(self): def line_buffering(self):
return self._line_buffering return self._line_buffering
@property
def buffer(self):
return self._buffer
def seekable(self): def seekable(self):
return self._seekable return self._seekable
...@@ -1734,8 +1742,8 @@ class TextIOWrapper(TextIOBase): ...@@ -1734,8 +1742,8 @@ class TextIOWrapper(TextIOBase):
if self.buffer is None: if self.buffer is None:
raise ValueError("buffer is already detached") raise ValueError("buffer is already detached")
self.flush() self.flush()
buffer = self.buffer buffer = self._buffer
self.buffer = None self._buffer = None
return buffer return buffer
def seek(self, cookie, whence=0): def seek(self, cookie, whence=0):
......
...@@ -730,6 +730,13 @@ class CommonBufferedTests: ...@@ -730,6 +730,13 @@ class CommonBufferedTests:
self.assertRaises(self.UnsupportedOperation, bufio.tell) self.assertRaises(self.UnsupportedOperation, bufio.tell)
self.assertRaises(self.UnsupportedOperation, bufio.seek, 0) self.assertRaises(self.UnsupportedOperation, bufio.seek, 0)
def test_readonly_attributes(self):
raw = self.MockRawIO()
buf = self.tp(raw)
x = self.MockRawIO()
with self.assertRaises(AttributeError):
buf.raw = x
class BufferedReaderTest(unittest.TestCase, CommonBufferedTests): class BufferedReaderTest(unittest.TestCase, CommonBufferedTests):
read_mode = "rb" read_mode = "rb"
...@@ -2245,6 +2252,12 @@ class TextIOWrapperTest(unittest.TestCase): ...@@ -2245,6 +2252,12 @@ class TextIOWrapperTest(unittest.TestCase):
self.assertRaises(self.UnsupportedOperation, txt.tell) self.assertRaises(self.UnsupportedOperation, txt.tell)
self.assertRaises(self.UnsupportedOperation, txt.seek, 0) self.assertRaises(self.UnsupportedOperation, txt.seek, 0)
def test_readonly_attributes(self):
txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii")
buf = self.BytesIO(self.testdata)
with self.assertRaises(AttributeError):
txt.buffer = buf
class CTextIOWrapperTest(TextIOWrapperTest): class CTextIOWrapperTest(TextIOWrapperTest):
def test_initialization(self): def test_initialization(self):
......
...@@ -11,6 +11,8 @@ Core and Builtins ...@@ -11,6 +11,8 @@ Core and Builtins
Library Library
------- -------
- Issue #10750: The ``raw`` attribute of buffered IO objects is now read-only.
- Deprecated assertDictContainsSubclass() in the unittest module. - Deprecated assertDictContainsSubclass() in the unittest module.
......
...@@ -1541,7 +1541,7 @@ static PyMethodDef bufferedreader_methods[] = { ...@@ -1541,7 +1541,7 @@ static PyMethodDef bufferedreader_methods[] = {
}; };
static PyMemberDef bufferedreader_members[] = { static PyMemberDef bufferedreader_members[] = {
{"raw", T_OBJECT, offsetof(buffered, raw), 0}, {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
{NULL} {NULL}
}; };
...@@ -1926,7 +1926,7 @@ static PyMethodDef bufferedwriter_methods[] = { ...@@ -1926,7 +1926,7 @@ static PyMethodDef bufferedwriter_methods[] = {
}; };
static PyMemberDef bufferedwriter_members[] = { static PyMemberDef bufferedwriter_members[] = {
{"raw", T_OBJECT, offsetof(buffered, raw), 0}, {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
{NULL} {NULL}
}; };
...@@ -2320,7 +2320,7 @@ static PyMethodDef bufferedrandom_methods[] = { ...@@ -2320,7 +2320,7 @@ static PyMethodDef bufferedrandom_methods[] = {
}; };
static PyMemberDef bufferedrandom_members[] = { static PyMemberDef bufferedrandom_members[] = {
{"raw", T_OBJECT, offsetof(buffered, raw), 0}, {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
{NULL} {NULL}
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment