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.
| 1232 | return pos |
| 1233 | |
| 1234 | class BufferedWriter(_BufferedIOMixin): |
| 1235 | |
| 1236 | """A buffer for a writeable sequential RawIO object. |
| 1237 | |
| 1238 | The constructor creates a BufferedWriter for the given writeable raw |
| 1239 | stream. If the buffer_size is not given, it defaults to |
| 1240 | DEFAULT_BUFFER_SIZE. |
| 1241 | """ |
| 1242 | |
| 1243 | def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): |
| 1244 | if not raw.writable(): |
| 1245 | raise OSError('"raw" argument must be writable.') |
| 1246 | |
| 1247 | _BufferedIOMixin.__init__(self, raw) |
| 1248 | if buffer_size <= 0: |
| 1249 | raise ValueError("invalid buffer size") |
| 1250 | self.buffer_size = buffer_size |
| 1251 | self._write_buf = bytearray() |
| 1252 | self._write_lock = Lock() |
| 1253 | |
| 1254 | def writable(self): |
| 1255 | return self.raw.writable() |
| 1256 | |
| 1257 | def write(self, b): |
| 1258 | if isinstance(b, str): |
| 1259 | raise TypeError("can't write str to binary stream") |
| 1260 | with self._write_lock: |
| 1261 | if self.closed: |
| 1262 | raise ValueError("write to closed file") |
| 1263 | # XXX we can implement some more tricks to try and avoid |
| 1264 | # partial writes |
| 1265 | if len(self._write_buf) > self.buffer_size: |
| 1266 | # We're full, so let's pre-flush the buffer. (This may |
| 1267 | # raise BlockingIOError with characters_written == 0.) |
| 1268 | self._flush_unlocked() |
| 1269 | before = len(self._write_buf) |
| 1270 | self._write_buf.extend(b) |
| 1271 | written = len(self._write_buf) - before |
| 1272 | if len(self._write_buf) > self.buffer_size: |
| 1273 | try: |
| 1274 | self._flush_unlocked() |
| 1275 | except BlockingIOError as e: |
| 1276 | if len(self._write_buf) > self.buffer_size: |
| 1277 | # We've hit the buffer_size. We have to accept a partial |
| 1278 | # write and cut back our buffer. |
| 1279 | overage = len(self._write_buf) - self.buffer_size |
| 1280 | written -= overage |
| 1281 | self._write_buf = self._write_buf[:self.buffer_size] |
| 1282 | raise BlockingIOError(e.errno, e.strerror, written) |
| 1283 | return written |
| 1284 | |
| 1285 | def truncate(self, pos=None): |
| 1286 | with self._write_lock: |
| 1287 | self._flush_unlocked() |
| 1288 | if pos is None: |
| 1289 | pos = self.raw.tell() |
| 1290 | return self.raw.truncate(pos) |
| 1291 |