@@ -31,6 +31,25 @@ def test_protocol():
31
31
assert loads (dumps (msg )) == msg
32
32
33
33
34
+ def test_default_compression ():
35
+ """Test that the default compression algorithm is lz4 -> snappy -> None.
36
+ If neither is installed, test that we don't fall back to the very slow zlib.
37
+ """
38
+ try :
39
+ import lz4 # noqa: F401
40
+
41
+ assert default_compression == "lz4"
42
+ return
43
+ except ImportError :
44
+ pass
45
+ try :
46
+ import snappy # noqa: F401
47
+
48
+ assert default_compression == "snappy"
49
+ except ImportError :
50
+ assert default_compression is None
51
+
52
+
34
53
@pytest .mark .parametrize (
35
54
"config,default" ,
36
55
[
@@ -49,8 +68,8 @@ def test_compression_config(config, default):
49
68
assert get_default_compression () == default
50
69
51
70
71
+ @pytest .mark .skipif (default_compression is None , reason = "requires lz4 or snappy" )
52
72
def test_compression_1 ():
53
- pytest .importorskip ("lz4" )
54
73
np = pytest .importorskip ("numpy" )
55
74
x = np .ones (1000000 )
56
75
b = x .tobytes ()
@@ -60,17 +79,17 @@ def test_compression_1():
60
79
assert {"x" : b } == y
61
80
62
81
82
+ @pytest .mark .skipif (default_compression is None , reason = "requires lz4 or snappy" )
63
83
def test_compression_2 ():
64
- pytest .importorskip ("lz4" )
65
84
np = pytest .importorskip ("numpy" )
66
85
x = np .random .random (10000 )
67
86
msg = dumps (to_serialize (x .data ))
68
87
compression = msgpack .loads (msg [1 ]).get ("compression" )
69
88
assert all (c is None for c in compression )
70
89
71
90
91
+ @pytest .mark .skipif (default_compression is None , reason = "requires lz4 or snappy" )
72
92
def test_compression_3 ():
73
- pytest .importorskip ("lz4" )
74
93
np = pytest .importorskip ("numpy" )
75
94
x = np .ones (1000000 )
76
95
frames = dumps ({"x" : Serialize (x .data )})
@@ -79,8 +98,8 @@ def test_compression_3():
79
98
assert {"x" : x .data } == y
80
99
81
100
101
+ @pytest .mark .skipif (default_compression is None , reason = "requires lz4 or snappy" )
82
102
def test_compression_without_deserialization ():
83
- pytest .importorskip ("lz4" )
84
103
np = pytest .importorskip ("numpy" )
85
104
x = np .ones (1000000 )
86
105
@@ -91,6 +110,18 @@ def test_compression_without_deserialization():
91
110
assert all (len (frame ) < 1000000 for frame in msg ["x" ].frames )
92
111
93
112
113
+ def test_lz4_decompression_avoids_deep_copy ():
114
+ """Test that lz4 output is a bytearray, not bytes, so that numpy deserialization is
115
+ not forced to perform a deep copy to obtain a writeable array.
116
+ Note that zlib, zstandard, and snappy don't have this option.
117
+ """
118
+ pytest .importorskip ("lz4" )
119
+ a = bytearray (1_000_000 )
120
+ b = compressions ["lz4" ]["compress" ](a )
121
+ c = compressions ["lz4" ]["decompress" ](b )
122
+ assert isinstance (c , bytearray )
123
+
124
+
94
125
def test_small ():
95
126
assert sum (map (nbytes , dumps (b"" ))) < 10
96
127
assert sum (map (nbytes , dumps (1 ))) < 10
@@ -106,7 +137,13 @@ def test_small_and_big():
106
137
107
138
@pytest .mark .parametrize (
108
139
"lib,compression" ,
109
- [(None , None ), ("zlib" , "zlib" ), ("lz4" , "lz4" ), ("zstandard" , "zstd" )],
140
+ [
141
+ (None , None ),
142
+ ("zlib" , "zlib" ),
143
+ ("lz4" , "lz4" ),
144
+ ("snappy" , "snappy" ),
145
+ ("zstandard" , "zstd" ),
146
+ ],
110
147
)
111
148
def test_maybe_compress (lib , compression ):
112
149
if lib :
@@ -126,7 +163,13 @@ def test_maybe_compress(lib, compression):
126
163
127
164
@pytest .mark .parametrize (
128
165
"lib,compression" ,
129
- [(None , None ), ("zlib" , "zlib" ), ("lz4" , "lz4" ), ("zstandard" , "zstd" )],
166
+ [
167
+ (None , None ),
168
+ ("zlib" , "zlib" ),
169
+ ("lz4" , "lz4" ),
170
+ ("snappy" , "snappy" ),
171
+ ("zstandard" , "zstd" ),
172
+ ],
130
173
)
131
174
def test_compression_thread_safety (lib , compression ):
132
175
if lib :
@@ -164,7 +207,13 @@ def test_compress_decompress(fn):
164
207
165
208
@pytest .mark .parametrize (
166
209
"lib,compression" ,
167
- [(None , None ), ("zlib" , "zlib" ), ("lz4" , "lz4" ), ("zstandard" , "zstd" )],
210
+ [
211
+ (None , None ),
212
+ ("zlib" , "zlib" ),
213
+ ("lz4" , "lz4" ),
214
+ ("snappy" , "snappy" ),
215
+ ("zstandard" , "zstd" ),
216
+ ],
168
217
)
169
218
def test_maybe_compress_config_default (lib , compression ):
170
219
if lib :
@@ -183,9 +232,9 @@ def test_maybe_compress_config_default(lib, compression):
183
232
assert compressions [rc ]["decompress" ](rd ) == payload
184
233
185
234
235
+ @pytest .mark .skipif (default_compression is None , reason = "requires lz4 or snappy" )
186
236
def test_maybe_compress_sample ():
187
237
np = pytest .importorskip ("numpy" )
188
- lz4 = pytest .importorskip ("lz4" )
189
238
payload = np .random .randint (0 , 255 , size = 10000 ).astype ("u1" ).tobytes ()
190
239
fmt , compressed = maybe_compress (payload )
191
240
assert fmt is None
@@ -202,10 +251,9 @@ def test_large_bytes():
202
251
assert len (frames [1 ]) < 1000
203
252
204
253
205
- @pytest .mark .slow
254
+ @pytest .mark .skipif ( default_compression is None , reason = "requires lz4 or snappy" )
206
255
def test_large_messages ():
207
256
np = pytest .importorskip ("numpy" )
208
- pytest .importorskip ("lz4" )
209
257
if MEMORY_LIMIT < 8e9 :
210
258
pytest .skip ("insufficient memory" )
211
259
@@ -248,8 +296,8 @@ def test_loads_deserialize_False():
248
296
assert result == 123
249
297
250
298
299
+ @pytest .mark .skipif (default_compression is None , reason = "requires lz4 or snappy" )
251
300
def test_loads_without_deserialization_avoids_compression ():
252
- pytest .importorskip ("lz4" )
253
301
b = b"0" * 100000
254
302
255
303
msg = {"x" : 1 , "data" : to_serialize (b )}
@@ -311,12 +359,12 @@ def test_dumps_loads_Serialized():
311
359
assert result == result3
312
360
313
361
362
+ @pytest .mark .skipif (default_compression is None , reason = "requires lz4 or snappy" )
314
363
def test_maybe_compress_memoryviews ():
315
364
np = pytest .importorskip ("numpy" )
316
- pytest .importorskip ("lz4" )
317
365
x = np .arange (1000000 , dtype = "int64" )
318
366
compression , payload = maybe_compress (x .data )
319
- assert compression == "lz4"
367
+ assert compression == default_compression
320
368
assert len (payload ) < x .nbytes * 0.75
321
369
322
370
0 commit comments