add lzma compression

needs python 3.3+, on 3.2 it won't be available.
This commit is contained in:
Thomas Waldmann 2015-08-03 00:31:33 +02:00
parent 946507aeaf
commit 4c0012bddf
4 changed files with 61 additions and 8 deletions

View file

@ -641,12 +641,14 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
help='select compression algorithm and level, by giving a number: '
'0 == no compression [default], '
'1..9 == zlib level 1..9, '
'10 == lz4. '
'10 == lz4, '
'20-29 == lzma level 0..9.'
'Alternatively, you can also give a name and optionally additional args: '
'null == no compression, '
'zlib == zlib (default level 6), '
'zlib,0 .. zlib,9 == zlib (with level 0..9), '
'lz4 == lz4.')
'lz4 == lz4, '
'lzma,0 .. lzma,9 == lzma (with level 0..9).')
subparser.add_argument('archive', metavar='ARCHIVE',
type=location_validator(archive=True),
help='archive to create')

View file

@ -1,4 +1,8 @@
import zlib
try:
import lzma
except ImportError:
lzma = None
cdef extern from "lz4.h":
int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) nogil
@ -104,6 +108,29 @@ cdef class LZ4(CompressorBase):
return dest[:osize]
class LZMA(CompressorBase):
"""
lzma compression / decompression (python 3.3+ stdlib)
"""
ID = b'\x02\x00'
name = 'lzma'
def __init__(self, level=6, **kwargs):
super().__init__(**kwargs)
self.level = level
if lzma is None:
raise ValueError('No lzma support found.')
def compress(self, data):
# we do not need integrity checks in lzma, we do that already
data = lzma.compress(data, preset=self.level, check=lzma.CHECK_NONE)
return super().compress(data)
def decompress(self, data):
data = super().decompress(data)
return lzma.decompress(data)
class ZLIB(CompressorBase):
"""
zlib compression / decompression (python stdlib)
@ -137,8 +164,9 @@ COMPRESSOR_TABLE = {
CNULL.name: CNULL,
LZ4.name: LZ4,
ZLIB.name: ZLIB,
LZMA.name: LZMA,
}
COMPRESSOR_LIST = [LZ4, CNULL, ZLIB, ] # check fast stuff first
COMPRESSOR_LIST = [LZ4, CNULL, ZLIB, LZMA, ] # check fast stuff first
def get_compressor(name, **kwargs):
cls = COMPRESSOR_TABLE[name]

View file

@ -302,13 +302,15 @@ def CompressionSpec(s):
return dict(name='zlib', level=compression)
if compression == 10:
return dict(name='lz4')
if 20 <= compression <= 29:
return dict(name='lzma', level=compression-20)
raise ValueError
except ValueError:
# --compression algo[,...]
name = compression
if name in ('null', 'lz4', ):
return dict(name=name)
if name == 'zlib':
if name in ('zlib', 'lzma', ):
if count < 2:
level = 6 # default compression level in py stdlib
elif count == 2:
@ -317,7 +319,7 @@ def CompressionSpec(s):
raise ValueError
else:
raise ValueError
return dict(name='zlib', level=level)
return dict(name=name, level=level)
raise ValueError

View file

@ -1,4 +1,8 @@
import zlib
try:
import lzma
except ImportError:
lzma = None
import pytest
@ -6,7 +10,7 @@ from ..compress import get_compressor, Compressor, CNULL, ZLIB, LZ4
buffer = bytes(2**16)
data = b'fooooooooobaaaaaaaar'
data = b'fooooooooobaaaaaaaar' * 10
params = dict(name='zlib', level=6, buffer=buffer)
@ -46,6 +50,16 @@ def test_zlib():
assert data == Compressor(**params).decompress(cdata) # autodetect
def test_lzma():
if lzma is None:
pytest.skip("No lzma support found.")
c = get_compressor(name='lzma')
cdata = c.compress(data)
assert len(cdata) < len(data)
assert data == c.decompress(cdata)
assert data == Compressor(**params).decompress(cdata) # autodetect
def test_autodetect_invalid():
with pytest.raises(ValueError):
Compressor(**params).decompress(b'\xff\xfftotalcrap')
@ -68,13 +82,20 @@ def test_zlib_compat():
def test_compressor():
for params in [
params_list = [
dict(name='null', buffer=buffer),
dict(name='lz4', buffer=buffer),
dict(name='zlib', level=0, buffer=buffer),
dict(name='zlib', level=6, buffer=buffer),
dict(name='zlib', level=9, buffer=buffer),
]:
]
if lzma:
params_list += [
dict(name='lzma', level=0, buffer=buffer),
dict(name='lzma', level=6, buffer=buffer),
dict(name='lzma', level=9, buffer=buffer),
]
for params in params_list:
c = Compressor(**params)
assert data == c.decompress(c.compress(data))