Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ python -m pip install "pymongo[snappy]"
```

Wire protocol compression with zstandard requires
[zstandard](https://pypi.org/project/zstandard):
[backports.zstd](https://pypi.org/project/backports.zstd)
when used with Python versions before 3.14:

```bash
python -m pip install "pymongo[zstd]"
Expand Down
1 change: 1 addition & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ PyMongo 4.16 brings a number of changes including:
Python 3.10+. The minimum version is ``2.6.1`` to account for `CVE-2023-29483 <https://www.cve.org/CVERecord?id=CVE-2023-29483>`_.
- Removed support for Eventlet.
Eventlet is actively being sunset by its maintainers and has compatibility issues with PyMongo's dnspython dependency.
- Use Zstandard support from the standard library for Python 3.14+, and use ``backports.zstd`` for older versions.

Changes in Version 4.15.3 (2025/10/07)
--------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions pymongo/asynchronous/mongo_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,8 @@ def __init__(
with the server. Currently supported options are "snappy", "zlib"
and "zstd". Support for snappy requires the
`python-snappy <https://pypi.org/project/python-snappy/>`_ package.
zlib support requires the Python standard library zlib module. zstd
requires the `zstandard <https://pypi.org/project/zstandard/>`_
zlib support requires the Python standard library zlib module. For
Python before 3.14 zstd requires the `backports.zstd <https://pypi.org/project/backports.zstd/>`_
package. By default no compression is used. Compression support
must also be enabled on the server. MongoDB 3.6+ supports snappy
and zlib compression. MongoDB 4.2+ adds support for zstd.
Expand Down
42 changes: 27 additions & 15 deletions pymongo/compression_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.
from __future__ import annotations

import sys
import warnings
from typing import Any, Iterable, Optional, Union

Expand Down Expand Up @@ -44,7 +45,10 @@ def _have_zlib() -> bool:

def _have_zstd() -> bool:
try:
import zstandard # noqa: F401
if sys.version_info >= (3, 14):
from compression import zstd
else:
from backports import zstd # noqa: F401

return True
except ImportError:
Expand Down Expand Up @@ -79,11 +83,18 @@ def validate_compressors(dummy: Any, value: Union[str, Iterable[str]]) -> list[s
)
elif compressor == "zstd" and not _have_zstd():
compressors.remove(compressor)
warnings.warn(
"Wire protocol compression with zstandard is not available. "
"You must install the zstandard module for zstandard support.",
stacklevel=2,
)
if sys.version_info >= (3, 14):
warnings.warn(
"Wire protocol compression with zstandard is not available. "
"The compression.zstd module is not available.",
stacklevel=2,
)
else:
warnings.warn(
"Wire protocol compression with zstandard is not available. "
"You must install the backports.zstd module for zstandard support.",
stacklevel=2,
)
return compressors


Expand Down Expand Up @@ -144,12 +155,12 @@ class ZstdContext:

@staticmethod
def compress(data: bytes) -> bytes:
# ZstdCompressor is not thread safe.
# TODO: Use a pool?

import zstandard
if sys.version_info >= (3, 14):
from compression import zstd
else:
from backports import zstd

return zstandard.ZstdCompressor().compress(data)
return zstd.compress(data)


def decompress(data: bytes | memoryview, compressor_id: int) -> bytes:
Expand All @@ -166,10 +177,11 @@ def decompress(data: bytes | memoryview, compressor_id: int) -> bytes:

return zlib.decompress(data)
elif compressor_id == ZstdContext.compressor_id:
# ZstdDecompressor is not thread safe.
# TODO: Use a pool?
import zstandard
if sys.version_info >= (3, 14):
from compression import zstd
else:
from backports import zstd

return zstandard.ZstdDecompressor().decompress(data)
return zstd.decompress(data)
else:
raise ValueError("Unknown compressorId %d" % (compressor_id,))
4 changes: 2 additions & 2 deletions pymongo/synchronous/mongo_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,8 @@ def __init__(
with the server. Currently supported options are "snappy", "zlib"
and "zstd". Support for snappy requires the
`python-snappy <https://pypi.org/project/python-snappy/>`_ package.
zlib support requires the Python standard library zlib module. zstd
requires the `zstandard <https://pypi.org/project/zstandard/>`_
zlib support requires the Python standard library zlib module. For
Python before 3.14 zstd requires the `backports.zstd <https://pypi.org/project/backports.zstd/>`_
package. By default no compression is used. Compression support
must also be enabled on the server. MongoDB 3.6+ supports snappy
and zlib compression. MongoDB 4.2+ adds support for zstd.
Expand Down
2 changes: 1 addition & 1 deletion requirements/zstd.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
zstandard
backports.zstd>=1.0.0;python_version<'3.14'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer we keep using zstandard to limit the scope of these changes.

Loading