add brotli support
This commit is contained in:
@@ -2,9 +2,9 @@ dest: /path/to/store/backup/files # The programs will store database and backup
|
|||||||
enable_pcre2: false # Optional. Default value: false. Try to use PCRE2 first. PCRE2 may be a little slower than internal regex library.
|
enable_pcre2: false # Optional. Default value: false. Try to use PCRE2 first. PCRE2 may be a little slower than internal regex library.
|
||||||
remove_old_files: true # Optional. Default value: true. Remove unneeded backup files which already deleted in source tree when backuping files.
|
remove_old_files: true # Optional. Default value: true. Remove unneeded backup files which already deleted in source tree when backuping files.
|
||||||
ignore_hidden_files: true # Optional. Default value: true. Whether to ignore files which its name starts with ".". Only effect folder which type is "path".
|
ignore_hidden_files: true # Optional. Default value: true. Whether to ignore files which its name starts with ".". Only effect folder which type is "path".
|
||||||
compress_method: "bzip2" # Optional. Default value: null. Supported value: "bzip2", "gzip", "lzma", "lzip", "zstd", "snappy"
|
compress_method: "bzip2" # Optional. Default value: null. Supported value: "bzip2", "gzip", "lzma", "lzip", "zstd", "snappy", "brotli"
|
||||||
# Optional. Default value: null. bzip2 support 1-9 (Default: 9). gzip support 0-9 (Default: 9). lzma or lzip support 0-9 (Default: 6).
|
# Optional. Default value: null. bzip2 support 1-9 (Default: 9). gzip support 0-9 (Default: 9). lzma or lzip support 0-9 (Default: 6).
|
||||||
# zstd support 0-22 (Default: 3).
|
# zstd support 0-22 (Default: 3). brotli support 0-11 (Default: unset).
|
||||||
compress_level: 6
|
compress_level: 6
|
||||||
programs:
|
programs:
|
||||||
- name: Your program name # This name is used to identify different application.
|
- name: Your program name # This name is used to identify different application.
|
||||||
|
|||||||
@@ -37,6 +37,14 @@ try:
|
|||||||
have_snappy = True
|
have_snappy = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
have_snappy = False
|
have_snappy = False
|
||||||
|
try:
|
||||||
|
from brotli import (
|
||||||
|
Compressor as BrotliCompressor,
|
||||||
|
Decompressor as BrotliDecompressor,
|
||||||
|
)
|
||||||
|
have_brotli = True
|
||||||
|
except ImportError:
|
||||||
|
have_brotli = False
|
||||||
from enum import IntEnum, unique
|
from enum import IntEnum, unique
|
||||||
try:
|
try:
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
@@ -54,6 +62,7 @@ class CompressMethod(IntEnum):
|
|||||||
LZIP = 3
|
LZIP = 3
|
||||||
ZSTD = 4
|
ZSTD = 4
|
||||||
SNAPPY = 5
|
SNAPPY = 5
|
||||||
|
BROTLI = 6
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_str(v: str) -> IntEnum:
|
def from_str(v: str) -> IntEnum:
|
||||||
@@ -71,6 +80,8 @@ class CompressMethod(IntEnum):
|
|||||||
return CompressMethod.ZSTD
|
return CompressMethod.ZSTD
|
||||||
elif t == "snappy":
|
elif t == "snappy":
|
||||||
return CompressMethod.SNAPPY
|
return CompressMethod.SNAPPY
|
||||||
|
elif t == "brotli":
|
||||||
|
return CompressMethod.BROTLI
|
||||||
else:
|
else:
|
||||||
raise TypeError('Must be str.')
|
raise TypeError('Must be str.')
|
||||||
|
|
||||||
@@ -140,6 +151,17 @@ class CompressConfig:
|
|||||||
raise NotImplementedError("snappy not supported.")
|
raise NotImplementedError("snappy not supported.")
|
||||||
self._level = None
|
self._level = None
|
||||||
self._ext = ".snappy"
|
self._ext = ".snappy"
|
||||||
|
elif self._method == CompressMethod.BROTLI:
|
||||||
|
if not have_brotli:
|
||||||
|
raise NotImplementedError("brotli not supported.")
|
||||||
|
if level is None:
|
||||||
|
self._level = None
|
||||||
|
else:
|
||||||
|
if isinstance(level, int) and level >= 0 and level <= 11:
|
||||||
|
self._level = level
|
||||||
|
else:
|
||||||
|
raise ValueError('brotli: compress_level should be 0-11.')
|
||||||
|
self._ext = '.br'
|
||||||
self._chunk_size = 131072
|
self._chunk_size = 131072
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@@ -176,6 +198,8 @@ if have_zstd:
|
|||||||
supported_exts.append('.zst')
|
supported_exts.append('.zst')
|
||||||
if have_snappy:
|
if have_snappy:
|
||||||
supported_exts.append('.snappy')
|
supported_exts.append('.snappy')
|
||||||
|
if have_brotli:
|
||||||
|
supported_exts.append('.br')
|
||||||
|
|
||||||
|
|
||||||
def sizeof_fmt(num, suffix='B'):
|
def sizeof_fmt(num, suffix='B'):
|
||||||
@@ -247,6 +271,21 @@ def compress(src: str, dest: str, c: CompressConfig, name: str, prog: str):
|
|||||||
f.write(b)
|
f.write(b)
|
||||||
a = t.read(cs)
|
a = t.read(cs)
|
||||||
del a, b, o
|
del a, b, o
|
||||||
|
elif c.method == CompressMethod.BROTLI:
|
||||||
|
k = {}
|
||||||
|
if c.level is not None:
|
||||||
|
k['quality'] = c.level
|
||||||
|
with open(src, 'rb') as t:
|
||||||
|
with open(fn, 'wb') as f:
|
||||||
|
o = BrotliCompressor(**k)
|
||||||
|
a = t.read(cs)
|
||||||
|
while a != b'':
|
||||||
|
b = o.process(a)
|
||||||
|
f.write(b)
|
||||||
|
a = t.read(cs)
|
||||||
|
f.write(o.finish())
|
||||||
|
del a, b, o
|
||||||
|
del k
|
||||||
i = compress_info(getsize(src), getsize(fn))
|
i = compress_info(getsize(src), getsize(fn))
|
||||||
print(f'{prog}: Compressed {src}({name}) -> {fn} ({i})')
|
print(f'{prog}: Compressed {src}({name}) -> {fn} ({i})')
|
||||||
del i
|
del i
|
||||||
@@ -311,5 +350,17 @@ def decompress(src: str, dest: str, c: CompressConfig, name: str, prog: str):
|
|||||||
a = f.read(cs)
|
a = f.read(cs)
|
||||||
o.flush()
|
o.flush()
|
||||||
del a, b, o
|
del a, b, o
|
||||||
|
elif c.method == CompressMethod.BROTLI:
|
||||||
|
with open(fn, 'rb') as f:
|
||||||
|
with open(dest, 'wb') as t:
|
||||||
|
o = BrotliDecompressor()
|
||||||
|
a = f.read(cs)
|
||||||
|
while a != b'':
|
||||||
|
b = o.process(a)
|
||||||
|
t.write(b)
|
||||||
|
a = f.read(cs)
|
||||||
|
if not o.is_finished():
|
||||||
|
raise ValueError('Read all datas from file but seems not finished.') # noqa: E501
|
||||||
|
del a, b, o
|
||||||
i = compress_info(getsize(dest), getsize(fn))
|
i = compress_info(getsize(dest), getsize(fn))
|
||||||
print(f'{prog}: Decompressed {fn}({name}) -> {dest} ({i})')
|
print(f'{prog}: Decompressed {fn}({name}) -> {dest} ({i})')
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ pyyaml
|
|||||||
plyvel[leveldb]
|
plyvel[leveldb]
|
||||||
lzip[lzip]
|
lzip[lzip]
|
||||||
python-snappy[snappy]
|
python-snappy[snappy]
|
||||||
|
brotli[brotli]
|
||||||
|
|||||||
Reference in New Issue
Block a user