| 1143 | |
| 1144 | |
| 1145 | class _ZipWriteFile(io.BufferedIOBase): |
| 1146 | def __init__(self, zf, zinfo, zip64): |
| 1147 | self._zinfo = zinfo |
| 1148 | self._zip64 = zip64 |
| 1149 | self._zipfile = zf |
| 1150 | self._compressor = _get_compressor(zinfo.compress_type, |
| 1151 | zinfo._compresslevel) |
| 1152 | self._file_size = 0 |
| 1153 | self._compress_size = 0 |
| 1154 | self._crc = 0 |
| 1155 | |
| 1156 | @property |
| 1157 | def _fileobj(self): |
| 1158 | return self._zipfile.fp |
| 1159 | |
| 1160 | def writable(self): |
| 1161 | return True |
| 1162 | |
| 1163 | def write(self, data): |
| 1164 | if self.closed: |
| 1165 | raise ValueError('I/O operation on closed file.') |
| 1166 | |
| 1167 | # Accept any data that supports the buffer protocol |
| 1168 | if isinstance(data, (bytes, bytearray)): |
| 1169 | nbytes = len(data) |
| 1170 | else: |
| 1171 | data = memoryview(data) |
| 1172 | nbytes = data.nbytes |
| 1173 | self._file_size += nbytes |
| 1174 | |
| 1175 | self._crc = crc32(data, self._crc) |
| 1176 | if self._compressor: |
| 1177 | data = self._compressor.compress(data) |
| 1178 | self._compress_size += len(data) |
| 1179 | self._fileobj.write(data) |
| 1180 | return nbytes |
| 1181 | |
| 1182 | def close(self): |
| 1183 | if self.closed: |
| 1184 | return |
| 1185 | try: |
| 1186 | super().close() |
| 1187 | # Flush any data from the compressor, and update header info |
| 1188 | if self._compressor: |
| 1189 | buf = self._compressor.flush() |
| 1190 | self._compress_size += len(buf) |
| 1191 | self._fileobj.write(buf) |
| 1192 | self._zinfo.compress_size = self._compress_size |
| 1193 | else: |
| 1194 | self._zinfo.compress_size = self._file_size |
| 1195 | self._zinfo.CRC = self._crc |
| 1196 | self._zinfo.file_size = self._file_size |
| 1197 | |
| 1198 | if not self._zip64: |
| 1199 | if self._file_size > ZIP64_LIMIT: |
| 1200 | raise RuntimeError("File size too large, try using force_zip64") |
| 1201 | if self._compress_size > ZIP64_LIMIT: |
| 1202 | raise RuntimeError("Compressed size too large, try using force_zip64") |