A buffer for a writeable sequential RawIO object. The constructor creates a BufferedWriter for the given writeable raw stream. If the buffer_size is not given, it defaults to DEFAULT_BUFFER_SIZE.
| 1213 | return pos |
| 1214 | |
| 1215 | class BufferedWriter(_BufferedIOMixin): |
| 1216 | |
| 1217 | """A buffer for a writeable sequential RawIO object. |
| 1218 | |
| 1219 | The constructor creates a BufferedWriter for the given writeable raw |
| 1220 | stream. If the buffer_size is not given, it defaults to |
| 1221 | DEFAULT_BUFFER_SIZE. |
| 1222 | """ |
| 1223 | |
| 1224 | def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): |
| 1225 | if not raw.writable(): |
| 1226 | raise OSError('"raw" argument must be writable.') |
| 1227 | |
| 1228 | _BufferedIOMixin.__init__(self, raw) |
| 1229 | if buffer_size <= 0: |
| 1230 | raise ValueError("invalid buffer size") |
| 1231 | self.buffer_size = buffer_size |
| 1232 | self._write_buf = bytearray() |
| 1233 | self._write_lock = Lock() |
| 1234 | |
| 1235 | def writable(self): |
| 1236 | return self.raw.writable() |
| 1237 | |
| 1238 | def write(self, b): |
| 1239 | if isinstance(b, str): |
| 1240 | raise TypeError("can't write str to binary stream") |
| 1241 | with self._write_lock: |
| 1242 | if self.closed: |
| 1243 | raise ValueError("write to closed file") |
| 1244 | # XXX we can implement some more tricks to try and avoid |
| 1245 | # partial writes |
| 1246 | if len(self._write_buf) > self.buffer_size: |
| 1247 | # We're full, so let's pre-flush the buffer. (This may |
| 1248 | # raise BlockingIOError with characters_written == 0.) |
| 1249 | self._flush_unlocked() |
| 1250 | before = len(self._write_buf) |
| 1251 | self._write_buf.extend(b) |
| 1252 | written = len(self._write_buf) - before |
| 1253 | if len(self._write_buf) > self.buffer_size: |
| 1254 | try: |
| 1255 | self._flush_unlocked() |
| 1256 | except BlockingIOError as e: |
| 1257 | if len(self._write_buf) > self.buffer_size: |
| 1258 | # We've hit the buffer_size. We have to accept a partial |
| 1259 | # write and cut back our buffer. |
| 1260 | overage = len(self._write_buf) - self.buffer_size |
| 1261 | written -= overage |
| 1262 | self._write_buf = self._write_buf[:self.buffer_size] |
| 1263 | raise BlockingIOError(e.errno, e.strerror, written) |
| 1264 | return written |
| 1265 | |
| 1266 | def truncate(self, pos=None): |
| 1267 | with self._write_lock: |
| 1268 | self._flush_unlocked() |
| 1269 | if pos is None: |
| 1270 | pos = self.raw.tell() |
| 1271 | return self.raw.truncate(pos) |
| 1272 |