MCPcopy Create free account
hub / github.com/aio-libs/aiohttp / ZLibCompressor

Class ZLibCompressor

aiohttp/compression_utils.py:193–265  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

191
192
193class ZLibCompressor:
194 def __init__(
195 self,
196 encoding: str | None = None,
197 suppress_deflate_header: bool = False,
198 level: int | None = None,
199 wbits: int | None = None,
200 strategy: int | None = None,
201 executor: Executor | None = None,
202 max_sync_chunk_size: int | None = MAX_SYNC_CHUNK_SIZE,
203 ):
204 self._executor = executor
205 self._max_sync_chunk_size = max_sync_chunk_size
206 self._mode = (
207 encoding_to_mode(encoding, suppress_deflate_header)
208 if wbits is None
209 else wbits
210 )
211 self._zlib_backend: Final = ZLibBackendWrapper(ZLibBackend._zlib_backend)
212
213 kwargs: CompressObjArgs = {}
214 kwargs["wbits"] = self._mode
215 if strategy is not None:
216 kwargs["strategy"] = strategy
217 if level is not None:
218 kwargs["level"] = level
219 self._compressor = self._zlib_backend.compressobj(**kwargs)
220
221 def compress_sync(self, data: Buffer) -> bytes:
222 return self._compressor.compress(data)
223
224 async def compress(self, data: Buffer) -> bytes:
225 """Compress the data and returned the compressed bytes.
226
227 Note that flush() must be called after the last call to compress()
228
229 If the data size is large than the max_sync_chunk_size, the compression
230 will be done in the executor. Otherwise, the compression will be done
231 in the event loop.
232
233 **WARNING: This method is NOT cancellation-safe when used with flush().**
234 If this operation is cancelled, the compressor state may be corrupted.
235 The connection MUST be closed after cancellation to avoid data corruption
236 in subsequent compress operations.
237
238 For cancellation-safe compression (e.g., WebSocket), the caller MUST wrap
239 compress() + flush() + send operations in a shield and lock to ensure atomicity.
240 """
241 # For large payloads, offload compression to executor to avoid blocking event loop
242 should_use_executor = (
243 self._max_sync_chunk_size is not None
244 and len(data) > self._max_sync_chunk_size
245 )
246 if should_use_executor:
247 return await asyncio.get_running_loop().run_in_executor(
248 self._executor, self._compressor.compress, data
249 )
250 return self.compress_sync(data)

Calls

no outgoing calls