summaryrefslogtreecommitdiffstats
path: root/Lib/_pyio.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/_pyio.py')
-rw-r--r--Lib/_pyio.py51
1 files changed, 25 insertions, 26 deletions
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index 3fa9325..a2faeb3 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -6,6 +6,7 @@ import os
import abc
import codecs
import warnings
+import errno
# Import _thread instead of threading to reduce startup cost
try:
from _thread import allocate_lock as Lock
@@ -720,8 +721,11 @@ class _BufferedIOMixin(BufferedIOBase):
def close(self):
if self.raw is not None and not self.closed:
- self.flush()
- self.raw.close()
+ try:
+ # may raise BlockingIOError or BrokenPipeError etc
+ self.flush()
+ finally:
+ self.raw.close()
def detach(self):
if self.raw is None:
@@ -1080,13 +1084,9 @@ class BufferedWriter(_BufferedIOMixin):
# XXX we can implement some more tricks to try and avoid
# partial writes
if len(self._write_buf) > self.buffer_size:
- # We're full, so let's pre-flush the buffer
- try:
- self._flush_unlocked()
- except BlockingIOError as e:
- # We can't accept anything else.
- # XXX Why not just let the exception pass through?
- raise BlockingIOError(e.errno, e.strerror, 0)
+ # We're full, so let's pre-flush the buffer. (This may
+ # raise BlockingIOError with characters_written == 0.)
+ self._flush_unlocked()
before = len(self._write_buf)
self._write_buf.extend(b)
written = len(self._write_buf) - before
@@ -1117,24 +1117,23 @@ class BufferedWriter(_BufferedIOMixin):
def _flush_unlocked(self):
if self.closed:
raise ValueError("flush of closed file")
- written = 0
- try:
- while self._write_buf:
- try:
- n = self.raw.write(self._write_buf)
- except IOError as e:
- if e.errno != EINTR:
- raise
- continue
- if n > len(self._write_buf) or n < 0:
- raise IOError("write() returned incorrect number of bytes")
- del self._write_buf[:n]
- written += n
- except BlockingIOError as e:
- n = e.characters_written
+ while self._write_buf:
+ try:
+ n = self.raw.write(self._write_buf)
+ except BlockingIOError:
+ raise RuntimeError("self.raw should implement RawIOBase: it "
+ "should not raise BlockingIOError")
+ except IOError as e:
+ if e.errno != EINTR:
+ raise
+ continue
+ if n is None:
+ raise BlockingIOError(
+ errno.EAGAIN,
+ "write could not complete without blocking", 0)
+ if n > len(self._write_buf) or n < 0:
+ raise IOError("write() returned incorrect number of bytes")
del self._write_buf[:n]
- written += n
- raise BlockingIOError(e.errno, e.strerror, written)
def tell(self):
return _BufferedIOMixin.tell(self) + len(self._write_buf)