def write(self, content): if 'w' not in self._mode: raise AttributeError("File was not opened in write mode.") self._is_dirty = True if self._multipart is None: self._multipart = self.obj.initiate_multipart_upload( **self._storage._get_write_parameters(self.obj.key)) if self.buffer_size <= self._buffer_file_size: self._flush_write_buffer() bstr = to_bytes(content) self._raw_bytes_written += len(bstr) return super().write(bstr)
def _compress_content(self, content): """Gzip a given string content.""" zbuf = io.BytesIO() # The GZIP header has a modification time attribute (see http://www.zlib.org/rfc-gzip.html) # This means each time a file is compressed it changes even if the other contents don't change # For S3 this defeats detection of changes using MD5 sums on gzipped files # Fixing the mtime at 0.0 at compression time avoids this problem with GzipFile(mode='wb', fileobj=zbuf, mtime=0.0) as zfile: zfile.write(to_bytes(content.read())) zbuf.seek(0) # Boto 2 returned the InMemoryUploadedFile with the file pointer replaced, # but Boto 3 seems to have issues with that. No need for fp.name in Boto3 # so just returning the BytesIO directly return zbuf
def readinto(self, buf: bytearray) -> Optional[int]: size = len(buf) while len(self.leftover) < size: chunk = to_bytes(self.raw.read(size)) if not chunk: if self.compress: self.leftover += self.compress.flush(zlib.Z_FINISH) self.compress = None break self.leftover += self.compress.compress(chunk) if len(self.leftover) == 0: return 0 output = self.leftover[:size] size = len(output) buf[:size] = output self.leftover = self.leftover[size:] return size
def write(self, content): if ('w' not in self._mode and '+' not in self._mode and 'a' not in self._mode): raise AttributeError("File was not opened in write mode.") self._is_dirty = True return super().write(to_bytes(content))