28
28
# Python built without zlib support.
29
29
_HAVE_ZLIB = False
30
30
31
+ try :
32
+ from zstandard import ZstdCompressor , ZstdDecompressor
33
+ _HAVE_ZSTD = True
34
+ except ImportError :
35
+ _HAVE_ZSTD = False
36
+
31
37
from pymongo .monitoring import _SENSITIVE_COMMANDS
32
38
33
- _SUPPORTED_COMPRESSORS = set (["snappy" , "zlib" ])
39
+ _SUPPORTED_COMPRESSORS = set (["snappy" , "zlib" , "zstd" ])
34
40
_NO_COMPRESSION = set (['ismaster' ])
35
41
_NO_COMPRESSION .update (_SENSITIVE_COMMANDS )
36
42
@@ -57,6 +63,11 @@ def validate_compressors(dummy, value):
57
63
warnings .warn (
58
64
"Wire protocol compression with zlib is not available. "
59
65
"The zlib module is not available." )
66
+ elif compressor == "zstd" and not _HAVE_ZSTD :
67
+ compressors .remove (compressor )
68
+ warnings .warn (
69
+ "Wire protocol compression with zstandard is not available. "
70
+ "You must install the zstandard module for zstandard support." )
60
71
return compressors
61
72
62
73
@@ -83,6 +94,8 @@ def get_compression_context(self, compressors):
83
94
return SnappyContext ()
84
95
elif chosen == "zlib" :
85
96
return ZlibContext (self .zlib_compression_level )
97
+ elif chosen == "zstd" :
98
+ return ZstdContext ()
86
99
87
100
88
101
def _zlib_no_compress (data ):
@@ -113,6 +126,16 @@ def __init__(self, level):
113
126
self .compress = lambda data : zlib .compress (data , level )
114
127
115
128
129
+ class ZstdContext (object ):
130
+ compressor_id = 3
131
+
132
+ @staticmethod
133
+ def compress (data ):
134
+ # ZstdCompressor is not thread safe.
135
+ # TODO: Use a pool?
136
+ return ZstdCompressor ().compress (data )
137
+
138
+
116
139
def decompress (data , compressor_id ):
117
140
if compressor_id == SnappyContext .compressor_id :
118
141
# python-snappy doesn't support the buffer interface.
@@ -126,5 +149,9 @@ def decompress(data, compressor_id):
126
149
return snappy .uncompress (bytes (data ))
127
150
elif compressor_id == ZlibContext .compressor_id :
128
151
return zlib .decompress (data )
152
+ elif compressor_id == ZstdContext .compressor_id :
153
+ # ZstdDecompressor is not thread safe.
154
+ # TODO: Use a pool?
155
+ return ZstdDecompressor ().decompress (data )
129
156
else :
130
157
raise ValueError ("Unknown compressorId %d" % (compressor_id ,))
0 commit comments