mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
Issue #21802: The reader in BufferedRWPair now is closed even when closing
writer failed in BufferedRWPair.close().
This commit is contained in:
parent
8ffe917cee
commit
7665be6087
4 changed files with 64 additions and 6 deletions
|
@ -1230,8 +1230,10 @@ class BufferedRWPair(BufferedIOBase):
|
||||||
return self.writer.flush()
|
return self.writer.flush()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.writer.close()
|
try:
|
||||||
self.reader.close()
|
self.writer.close()
|
||||||
|
finally:
|
||||||
|
self.reader.close()
|
||||||
|
|
||||||
def isatty(self):
|
def isatty(self):
|
||||||
return self.reader.isatty() or self.writer.isatty()
|
return self.reader.isatty() or self.writer.isatty()
|
||||||
|
|
|
@ -1588,6 +1588,53 @@ class BufferedRWPairTest(unittest.TestCase):
|
||||||
pair.close()
|
pair.close()
|
||||||
self.assertTrue(pair.closed)
|
self.assertTrue(pair.closed)
|
||||||
|
|
||||||
|
def test_reader_close_error_on_close(self):
|
||||||
|
def reader_close():
|
||||||
|
reader_non_existing
|
||||||
|
reader = self.MockRawIO()
|
||||||
|
reader.close = reader_close
|
||||||
|
writer = self.MockRawIO()
|
||||||
|
pair = self.tp(reader, writer)
|
||||||
|
with self.assertRaises(NameError) as err:
|
||||||
|
pair.close()
|
||||||
|
self.assertIn('reader_non_existing', str(err.exception))
|
||||||
|
self.assertTrue(pair.closed)
|
||||||
|
self.assertFalse(reader.closed)
|
||||||
|
self.assertTrue(writer.closed)
|
||||||
|
|
||||||
|
def test_writer_close_error_on_close(self):
|
||||||
|
def writer_close():
|
||||||
|
writer_non_existing
|
||||||
|
reader = self.MockRawIO()
|
||||||
|
writer = self.MockRawIO()
|
||||||
|
writer.close = writer_close
|
||||||
|
pair = self.tp(reader, writer)
|
||||||
|
with self.assertRaises(NameError) as err:
|
||||||
|
pair.close()
|
||||||
|
self.assertIn('writer_non_existing', str(err.exception))
|
||||||
|
self.assertFalse(pair.closed)
|
||||||
|
self.assertTrue(reader.closed)
|
||||||
|
self.assertFalse(writer.closed)
|
||||||
|
|
||||||
|
def test_reader_writer_close_error_on_close(self):
|
||||||
|
def reader_close():
|
||||||
|
reader_non_existing
|
||||||
|
def writer_close():
|
||||||
|
writer_non_existing
|
||||||
|
reader = self.MockRawIO()
|
||||||
|
reader.close = reader_close
|
||||||
|
writer = self.MockRawIO()
|
||||||
|
writer.close = writer_close
|
||||||
|
pair = self.tp(reader, writer)
|
||||||
|
with self.assertRaises(NameError) as err:
|
||||||
|
pair.close()
|
||||||
|
self.assertIn('reader_non_existing', str(err.exception))
|
||||||
|
self.assertIsInstance(err.exception.__context__, NameError)
|
||||||
|
self.assertIn('writer_non_existing', str(err.exception.__context__))
|
||||||
|
self.assertFalse(pair.closed)
|
||||||
|
self.assertFalse(reader.closed)
|
||||||
|
self.assertFalse(writer.closed)
|
||||||
|
|
||||||
def test_isatty(self):
|
def test_isatty(self):
|
||||||
class SelectableIsAtty(MockRawIO):
|
class SelectableIsAtty(MockRawIO):
|
||||||
def __init__(self, isatty):
|
def __init__(self, isatty):
|
||||||
|
|
|
@ -18,6 +18,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #21802: The reader in BufferedRWPair now is closed even when closing
|
||||||
|
writer failed in BufferedRWPair.close().
|
||||||
|
|
||||||
- Issue #23671: string.Template now allows to specify the "self" parameter as
|
- Issue #23671: string.Template now allows to specify the "self" parameter as
|
||||||
keyword argument. string.Formatter now allows to specify the "self" and
|
keyword argument. string.Formatter now allows to specify the "self" and
|
||||||
the "format_string" parameters as keyword arguments.
|
the "format_string" parameters as keyword arguments.
|
||||||
|
|
|
@ -2365,12 +2365,18 @@ bufferedrwpair_writable(rwpair *self, PyObject *args)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bufferedrwpair_close(rwpair *self, PyObject *args)
|
bufferedrwpair_close(rwpair *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
PyObject *exc = NULL, *val, *tb;
|
||||||
PyObject *ret = _forward_call(self->writer, &PyId_close, args);
|
PyObject *ret = _forward_call(self->writer, &PyId_close, args);
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
return NULL;
|
PyErr_Fetch(&exc, &val, &tb);
|
||||||
Py_DECREF(ret);
|
else
|
||||||
|
Py_DECREF(ret);
|
||||||
return _forward_call(self->reader, &PyId_close, args);
|
ret = _forward_call(self->reader, &PyId_close, args);
|
||||||
|
if (exc != NULL) {
|
||||||
|
_PyErr_ChainExceptions(exc, val, tb);
|
||||||
|
Py_CLEAR(ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue