| 100 | chunk_size = 1024 |
| 101 | |
| 102 | def save(self, filename, content): |
| 103 | filename = super().save(filename, content) |
| 104 | orig_path = self.path(filename) |
| 105 | compressed_path = "%s.br" % orig_path |
| 106 | |
| 107 | import brotli |
| 108 | |
| 109 | br_compressor = brotli.Compressor() |
| 110 | with open(orig_path, "rb") as f_in, open(compressed_path, "wb") as f_out: |
| 111 | for f_in_data in iter(lambda: f_in.read(self.chunk_size), b""): |
| 112 | compressed_data = br_compressor.process(f_in_data) |
| 113 | if not compressed_data: |
| 114 | compressed_data = br_compressor.flush() |
| 115 | f_out.write(compressed_data) |
| 116 | f_out.write(br_compressor.finish()) |
| 117 | # Ensure the file timestamps match. |
| 118 | # os.stat() returns nanosecond resolution on Linux, but os.utime() |
| 119 | # only sets microsecond resolution. Set times on both files to |
| 120 | # ensure they are equal. |
| 121 | stamp = time.time() |
| 122 | os.utime(orig_path, (stamp, stamp)) |
| 123 | os.utime(compressed_path, (stamp, stamp)) |
| 124 | |
| 125 | return filename |
| 126 | |
| 127 | |
| 128 | class DefaultStorage(LazyObject): |