# Unlimited decompression constants - different libraries use different conventions
ZLIB_MAX_LENGTH_UNLIMITED = 0# zlib uses 0 to mean unlimited
ZSTD_MAX_LENGTH_UNLIMITED = -1# zstd uses -1 to mean unlimited
class ZLibCompressObjProtocol(Protocol): def compress(self, data: Buffer) -> bytes: ... def flush(self, mode: int = ..., /) -> bytes: ...
class ZLibDecompressObjProtocol(Protocol): def decompress(self, data: Buffer, max_length: int = ...) -> bytes: ... def flush(self, length: int = ..., /) -> bytes: ...
@property def eof(self) -> bool: ...
class ZLibBackendProtocol(Protocol):
MAX_WBITS: int
Z_FULL_FLUSH: int
Z_SYNC_FLUSH: int
Z_BEST_SPEED: int
Z_FINISH: int
def compressobj(
self,
level: int = ...,
method: int = ...,
wbits: int = ...,
memLevel: int = ...,
strategy: int = ...,
zdict: Optional[Buffer] = ...,
) -> ZLibCompressObjProtocol: ... def decompressobj(
self, wbits: int = ..., zdict: Buffer = ...
) -> ZLibDecompressObjProtocol: ...
def compress(
self, data: Buffer, /, level: int = ..., wbits: int = ...
) -> bytes: ... def decompress(
self, data: Buffer, /, wbits: int = ..., bufsize: int = ...
) -> bytes: ...
class CompressObjArgs(TypedDict, total=False):
wbits: int
strategy: int
level: int
class ZLibBackendWrapper: def __init__(self, _zlib_backend: ZLibBackendProtocol):
self._zlib_backend: ZLibBackendProtocol = _zlib_backend
# Everything not explicitly listed in the Protocol we just pass through def __getattr__(self, attrname: str) -> Any: return getattr(self._zlib_backend, attrname)
async def compress(self, data: bytes) -> bytes: """Compress the data and returned the compressed bytes.
Note that flush() must be called after the last call to compress()
If the data size is large than the max_sync_chunk_size, the compression
will be done in the executor. Otherwise, the compression will be done in the event loop.
**WARNING: This method isNOT cancellation-safe when used with flush().** If this operation is cancelled, the compressor state may be corrupted.
The connection MUST be closed after cancellation to avoid data corruption in subsequent compress operations.
For cancellation-safe compression (e.g., WebSocket), the caller MUST wrap
compress() + flush() + send operations in a shield and lock to ensure atomicity. """ # For large payloads, offload compression to executor to avoid blocking event loop
should_use_executor = (
self._max_sync_chunk_size isnotNone and len(data) > self._max_sync_chunk_size
) if should_use_executor: return await asyncio.get_running_loop().run_in_executor(
self._executor, self._compressor.compress, data
) return self.compress_sync(data)
**WARNING: This method isNOT cancellation-safe when called after compress().**
The flush() operation accesses shared compressor state. If compress() was
cancelled, calling flush() may result in corrupted data. The connection MUST
be closed after compress() cancellation.
For cancellation-safe compression (e.g., WebSocket), the caller MUST wrap
compress() + flush() + send operations in a shield and lock to ensure atomicity. """ return self._compressor.flush(
mode if mode isnotNoneelse self._zlib_backend.Z_FINISH
)
class BrotliDecompressor(DecompressionBaseHandler): # Supports both 'brotlipy' and 'Brotli' packages # since they share an import name. The top branches # are for 'brotlipy' and bottom branches for 'Brotli' def __init__(
self,
executor: Optional[Executor] = None,
max_sync_chunk_size: Optional[int] = MAX_SYNC_CHUNK_SIZE,
) -> None: """Decompress data using the Brotli library.""" ifnot HAS_BROTLI: raise RuntimeError( "The brotli decompression is not available. " "Please install `Brotli` module"
)
self._obj = brotli.Decompressor()
super().__init__(executor=executor, max_sync_chunk_size=max_sync_chunk_size)
def decompress_sync(
self, data: Buffer, max_length: int = ZLIB_MAX_LENGTH_UNLIMITED
) -> bytes: """Decompress the given data.""" if hasattr(self._obj, "decompress"): return cast(bytes, self._obj.decompress(data, max_length)) return cast(bytes, self._obj.process(data, max_length))
def flush(self) -> bytes: """Flush the decompressor.""" if hasattr(self._obj, "flush"): return cast(bytes, self._obj.flush()) return b""
class ZSTDDecompressor(DecompressionBaseHandler): def __init__(
self,
executor: Optional[Executor] = None,
max_sync_chunk_size: Optional[int] = MAX_SYNC_CHUNK_SIZE,
) -> None: ifnot HAS_ZSTD: raise RuntimeError( "The zstd decompression is not available. " "Please install `backports.zstd` module"
)
self._obj = ZstdDecompressor()
super().__init__(executor=executor, max_sync_chunk_size=max_sync_chunk_size)
def decompress_sync(
self, data: bytes, max_length: int = ZLIB_MAX_LENGTH_UNLIMITED
) -> bytes: # zstd uses -1 for unlimited, while zlib uses 0 for unlimited # Convert the zlib convention (0=unlimited) to zstd convention (-1=unlimited)
zstd_max_length = (
ZSTD_MAX_LENGTH_UNLIMITED if max_length == ZLIB_MAX_LENGTH_UNLIMITED else max_length
) return self._obj.decompress(data, zstd_max_length)
def flush(self) -> bytes: return b""
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-08-25)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.