Merge branch 'master' of github.com:mongodb/mongo-python-driver

This commit is contained in:
Steven Silvester 2025-09-29 07:47:21 -05:00
commit 6bf76157df
No known key found for this signature in database
47 changed files with 775 additions and 1038 deletions

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,7 @@ from shrub.v3.shrub_service import ShrubService
##############
ALL_VERSIONS = ["4.2", "4.4", "5.0", "6.0", "7.0", "8.0", "rapid", "latest"]
CPYTHONS = ["3.10", "3.9", "3.11", "3.12", "3.13", "3.14"]
CPYTHONS = ["3.10", "3.11", "3.12", "3.13", "3.14"]
PYPYS = ["pypy3.10"]
ALL_PYTHONS = CPYTHONS + PYPYS
MIN_MAX_PYTHON = [CPYTHONS[0], CPYTHONS[-1]]

View File

@ -6,29 +6,29 @@ find_python3() {
PYTHON=""
# Find a suitable toolchain version, if available.
if [ "$(uname -s)" = "Darwin" ]; then
PYTHON="/Library/Frameworks/Python.Framework/Versions/3.9/bin/python3"
PYTHON="/Library/Frameworks/Python.Framework/Versions/3.10/bin/python3"
elif [ "Windows_NT" = "${OS:-}" ]; then # Magic variable in cygwin
PYTHON="C:/python/Python39/python.exe"
PYTHON="C:/python/Python310/python.exe"
else
# Prefer our own toolchain, fall back to mongodb toolchain if it has Python 3.9+.
if [ -f "/opt/python/3.9/bin/python3" ]; then
# Prefer our own toolchain, fall back to mongodb toolchain if it has Python 3.10+.
if [ -f "/opt/python/3.10/bin/python3" ]; then
PYTHON="/opt/python/Current/bin/python3"
elif is_python_39 "$(command -v /opt/mongodbtoolchain/v5/bin/python3)"; then
elif is_python_310 "$(command -v /opt/mongodbtoolchain/v5/bin/python3)"; then
PYTHON="/opt/mongodbtoolchain/v5/bin/python3"
elif is_python_39 "$(command -v /opt/mongodbtoolchain/v4/bin/python3)"; then
elif is_python_310 "$(command -v /opt/mongodbtoolchain/v4/bin/python3)"; then
PYTHON="/opt/mongodbtoolchain/v4/bin/python3"
elif is_python_39 "$(command -v /opt/mongodbtoolchain/v3/bin/python3)"; then
elif is_python_310 "$(command -v /opt/mongodbtoolchain/v3/bin/python3)"; then
PYTHON="/opt/mongodbtoolchain/v3/bin/python3"
fi
fi
# Add a fallback system python3 if it is available and Python 3.9+.
# Add a fallback system python3 if it is available and Python 3.10+.
if [ -z "$PYTHON" ]; then
if is_python_39 "$(command -v python3)"; then
if is_python_310 "$(command -v python3)"; then
PYTHON="$(command -v python3)"
fi
fi
if [ -z "$PYTHON" ]; then
echo "Cannot test without python3.9+ installed!"
echo "Cannot test without python3.10+ installed!"
exit 1
fi
echo "$PYTHON"
@ -99,15 +99,15 @@ testinstall () {
fi
}
# Function that returns success if the provided Python binary is version 3.9 or later
# Function that returns success if the provided Python binary is version 3.10 or later
# Usage:
# is_python_39 /path/to/python
# is_python_310 /path/to/python
# * param1: Python binary
is_python_39() {
is_python_310() {
if [ -z "$1" ]; then
return 1
elif $1 -c "import sys; exit(sys.version_info[:2] < (3, 9))"; then
# runs when sys.version_info[:2] >= (3, 9)
elif $1 -c "import sys; exit(sys.version_info[:2] < (3, 10))"; then
# runs when sys.version_info[:2] >= (3, 10)
return 0
else
return 1
@ -131,7 +131,7 @@ get_python_binary() {
else
PYTHON="/opt/python/$version/bin/python3"
fi
if is_python_39 "$(command -v $PYTHON)"; then
if is_python_310 "$(command -v $PYTHON)"; then
echo "$PYTHON"
else
echo "Could not find suitable python binary for '$version'" >&2

View File

@ -70,34 +70,26 @@ jobs:
platforms: all
- name: Install cibuildwheel
# Note: the default manylinux is manylinux2014
# Note: the default manylinux is manylinux_2_28
run: |
python -m pip install -U pip
python -m pip install "cibuildwheel>=2.20,<3"
python -m pip install "cibuildwheel>=3.2.0,<4"
- name: Build wheels
env:
CIBW_BUILD: ${{ matrix.buildplat[2] }}
run: python -m cibuildwheel --output-dir wheelhouse
- name: Build manylinux1 wheels
if: ${{ matrix.buildplat[1] == 'manylinux_x86_64' || matrix.buildplat[1] == 'manylinux_i686' }}
env:
CIBW_MANYLINUX_X86_64_IMAGE: manylinux1
CIBW_MANYLINUX_I686_IMAGE: manylinux1
CIBW_BUILD: "cp39-${{ matrix.buildplat[1] }} cp39-${{ matrix.buildplat[1] }}"
run: python -m cibuildwheel --output-dir wheelhouse
- name: Assert all versions in wheelhouse
if: ${{ ! startsWith(matrix.buildplat[1], 'macos') }}
run: |
ls wheelhouse/*cp39*.whl
ls wheelhouse/*cp310*.whl
ls wheelhouse/*cp311*.whl
ls wheelhouse/*cp312*.whl
ls wheelhouse/*cp313*.whl
ls wheelhouse/*cp314*.whl
# Free-threading builds:
ls wheelhouse/*cp313t*.whl
ls wheelhouse/*cp314t*.whl
- uses: actions/upload-artifact@v4
with:
@ -118,7 +110,7 @@ jobs:
- uses: actions/setup-python@v6
with:
# Build sdist on lowest supported Python
python-version: '3.9'
python-version: "3.10"
- name: Build SDist
run: |

View File

@ -26,7 +26,7 @@ jobs:
uses: astral-sh/setup-uv@b75a909f75acd358c2196fb9a5f1299a9a8868a4 # v5
with:
enable-cache: true
python-version: "3.9"
python-version: "3.10"
- name: Install just
run: uv tool install rust-just
- name: Install Python dependencies
@ -56,7 +56,7 @@ jobs:
matrix:
# Tests currently only pass on ubuntu on GitHub Actions.
os: [ubuntu-latest]
python-version: ["3.9", "pypy-3.10", "3.13t"]
python-version: ["3.10", "pypy-3.10", "3.13t"]
mongodb-version: ["8.0"]
name: CPython ${{ matrix.python-version }}-${{ matrix.os }}
@ -87,7 +87,7 @@ jobs:
uses: astral-sh/setup-uv@b75a909f75acd358c2196fb9a5f1299a9a8868a4 # v5
with:
enable-cache: true
python-version: "3.9"
python-version: "3.10"
- name: Install just
run: uv tool install rust-just
- id: setup-mongodb
@ -112,7 +112,7 @@ jobs:
uses: astral-sh/setup-uv@b75a909f75acd358c2196fb9a5f1299a9a8868a4 # v5
with:
enable-cache: true
python-version: "3.9"
python-version: "3.10"
- name: Install just
run: uv tool install rust-just
- name: Install dependencies
@ -131,7 +131,7 @@ jobs:
uses: astral-sh/setup-uv@b75a909f75acd358c2196fb9a5f1299a9a8868a4 # v5
with:
enable-cache: true
python-version: "3.9"
python-version: "3.10"
- name: Install just
run: uv tool install rust-just
- name: Install dependencies
@ -144,7 +144,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python: ["3.9", "3.11"]
python: ["3.10", "3.11"]
steps:
- uses: actions/checkout@v5
with:
@ -175,7 +175,7 @@ jobs:
cache: 'pip'
cache-dependency-path: 'pyproject.toml'
# Build sdist on lowest supported Python
python-version: '3.9'
python-version: "3.10"
- name: Build SDist
shell: bash
run: |
@ -209,7 +209,7 @@ jobs:
cache: 'pip'
cache-dependency-path: 'sdist/test/pyproject.toml'
# Test sdist on lowest supported Python
python-version: '3.9'
python-version: "3.10"
- id: setup-mongodb
uses: mongodb-labs/drivers-evergreen-tools@master
- name: Run connect test from sdist
@ -233,7 +233,7 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@b75a909f75acd358c2196fb9a5f1299a9a8868a4 # v5
with:
python-version: '3.9'
python-version: "3.10"
- id: setup-mongodb
uses: mongodb-labs/drivers-evergreen-tools@master
with:

View File

@ -16,7 +16,7 @@ be of interest or that has already been addressed.
## Supported Interpreters
PyMongo supports CPython 3.9+ and PyPy3.10+. Language features not
PyMongo supports CPython 3.10+ and PyPy3.10+. Language features not
supported by all interpreters can not be used.
## Style Guide

View File

@ -97,7 +97,7 @@ package that is incompatible with PyMongo.
## Dependencies
PyMongo supports CPython 3.9+ and PyPy3.10+.
PyMongo supports CPython 3.10+ and PyPy3.10+.
Required dependencies:

View File

@ -6,6 +6,9 @@ Changes in Version 4.16.0 (XXXX/XX/XX)
PyMongo 4.16 brings a number of changes including:
.. warning:: PyMongo 4.16 drops support for Python 3.9: Python 3.10+ is now required.
- Dropped support for Python 3.9.
- Removed invalid documents from :class:`bson.errors.InvalidDocument` error messages as
doing so may leak sensitive user data.
Instead, invalid documents are stored in :attr:`bson.errors.InvalidDocument.document`.

View File

@ -46,7 +46,6 @@ from pymongo.asynchronous.client_session import AsyncClientSession
from pymongo.asynchronous.collection import AsyncCollection
from pymongo.asynchronous.cursor import AsyncCursor
from pymongo.asynchronous.database import AsyncDatabase
from pymongo.asynchronous.helpers import anext
from pymongo.common import validate_string
from pymongo.errors import (
BulkWriteError,

View File

@ -57,7 +57,6 @@ from pymongo.synchronous.client_session import ClientSession
from pymongo.synchronous.collection import Collection
from pymongo.synchronous.cursor import Cursor
from pymongo.synchronous.database import Database
from pymongo.synchronous.helpers import next
_IS_SYNC = True

View File

@ -37,7 +37,6 @@ from bson import RE_TYPE, _convert_raw_document_lists_to_streams
from bson.code import Code
from bson.son import SON
from pymongo import _csot, helpers_shared
from pymongo.asynchronous.helpers import anext
from pymongo.collation import validate_collation_or_none
from pymongo.common import (
validate_is_document_type,

View File

@ -16,9 +16,7 @@
from __future__ import annotations
import asyncio
import builtins
import socket
import sys
from typing import (
Any,
Callable,
@ -86,17 +84,3 @@ async def _getaddrinfo(
return await loop.getaddrinfo(host, port, **kwargs) # type: ignore[return-value]
else:
return socket.getaddrinfo(host, port, **kwargs)
if sys.version_info >= (3, 10):
anext = builtins.anext
aiter = builtins.aiter
else:
async def anext(cls: Any) -> Any:
"""Compatibility function until we drop 3.9 support: https://docs.python.org/3/library/functions.html#anext."""
return await cls.__anext__()
def aiter(cls: Any) -> Any:
"""Compatibility function until we drop 3.9 support: https://docs.python.org/3/library/functions.html#anext."""
return cls.__aiter__()

View File

@ -55,7 +55,6 @@ from pymongo.message import (
_RawBatchQuery,
)
from pymongo.response import PinnedResponse
from pymongo.synchronous.helpers import next
from pymongo.typings import _Address, _CollationIn, _DocumentOut, _DocumentType
from pymongo.write_concern import validate_boolean

View File

@ -16,9 +16,7 @@
from __future__ import annotations
import asyncio
import builtins
import socket
import sys
from typing import (
Any,
Callable,
@ -86,17 +84,3 @@ def _getaddrinfo(
return loop.getaddrinfo(host, port, **kwargs) # type: ignore[return-value]
else:
return socket.getaddrinfo(host, port, **kwargs)
if sys.version_info >= (3, 10):
next = builtins.next
iter = builtins.iter
else:
def next(cls: Any) -> Any:
"""Compatibility function until we drop 3.9 support: https://docs.python.org/3/library/functions.html#next."""
return cls.__next__()
def iter(cls: Any) -> Any:
"""Compatibility function until we drop 3.9 support: https://docs.python.org/3/library/functions.html#next."""
return cls.__iter__()

View File

@ -35,6 +35,7 @@ classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Database",
"Typing :: Typed",
]
@ -260,8 +261,6 @@ partial_branches = ["if (.*and +)*not _use_c( and.*)*:"]
directory = "htmlcov"
[tool.cibuildwheel]
# Enable free-threaded support
free-threaded-support = true
skip = "pp* *-musllinux*"
build-frontend = "build"
test-command = "python {project}/tools/fail_if_no_c.py"

View File

@ -48,7 +48,6 @@ from bson.binary import ALL_UUID_REPRESENTATIONS, PYTHON_LEGACY, STANDARD, Binar
from bson.raw_bson import DEFAULT_RAW_BSON_OPTIONS, RawBSONDocument
from pymongo import AsyncMongoClient
from pymongo.asynchronous.command_cursor import AsyncCommandCursor
from pymongo.asynchronous.helpers import anext
from pymongo.errors import (
InvalidOperation,
OperationFailure,

View File

@ -92,7 +92,6 @@ from pymongo import event_loggers, message, monitoring
from pymongo.asynchronous.command_cursor import AsyncCommandCursor
from pymongo.asynchronous.cursor import AsyncCursor, CursorType
from pymongo.asynchronous.database import AsyncDatabase
from pymongo.asynchronous.helpers import anext
from pymongo.asynchronous.mongo_client import AsyncMongoClient
from pymongo.asynchronous.pool import (
AsyncConnection,

View File

@ -21,7 +21,6 @@ from test.asynchronous import AsyncIntegrationTest, async_client_context, unitte
from test.utils_shared import EventListener, OvertCommandListener
from typing import Any
from pymongo.asynchronous.helpers import anext
from pymongo.collation import (
Collation,
CollationAlternate,

View File

@ -51,7 +51,6 @@ from bson.son import SON
from pymongo import ASCENDING, DESCENDING, GEO2D, GEOSPHERE, HASHED, TEXT
from pymongo.asynchronous.collection import AsyncCollection, ReturnDocument
from pymongo.asynchronous.command_cursor import AsyncCommandCursor
from pymongo.asynchronous.helpers import anext
from pymongo.asynchronous.mongo_client import AsyncMongoClient
from pymongo.bulk_shared import BulkWriteError
from pymongo.cursor_shared import CursorType

View File

@ -46,7 +46,6 @@ from bson.code import Code
from bson.raw_bson import RawBSONDocument
from pymongo import ASCENDING, DESCENDING
from pymongo.asynchronous.cursor import AsyncCursor, CursorType
from pymongo.asynchronous.helpers import anext
from pymongo.collation import Collation
from pymongo.errors import ExecutionTimeout, InvalidOperation, OperationFailure, PyMongoError
from pymongo.operations import _IndexList

View File

@ -53,7 +53,6 @@ from bson.errors import InvalidDocument
from bson.int64 import Int64
from bson.raw_bson import RawBSONDocument
from pymongo.asynchronous.collection import ReturnDocument
from pymongo.asynchronous.helpers import anext
from pymongo.errors import DuplicateKeyError
from pymongo.message import _CursorAddress

View File

@ -42,7 +42,6 @@ from pymongo import helpers_shared
from pymongo.asynchronous import auth
from pymongo.asynchronous.collection import AsyncCollection
from pymongo.asynchronous.database import AsyncDatabase
from pymongo.asynchronous.helpers import anext
from pymongo.asynchronous.mongo_client import AsyncMongoClient
from pymongo.errors import (
CollectionInvalid,

View File

@ -40,7 +40,6 @@ from typing import Any, Dict, Mapping, Optional
import pytest
from pymongo.asynchronous.collection import AsyncCollection
from pymongo.asynchronous.helpers import anext
from pymongo.daemon import _spawn_daemon
from pymongo.uri_parser_shared import _parse_kms_tls_options

View File

@ -29,7 +29,6 @@ from test.asynchronous import AsyncIntegrationTest, async_client_context, unitte
from test.utils_shared import async_wait_until
import pymongo
from pymongo.asynchronous.helpers import anext
from pymongo.errors import ConnectionFailure, OperationFailure
from pymongo.read_concern import ReadConcern
from pymongo.read_preferences import ReadPreference

View File

@ -47,7 +47,6 @@ from gridfs.asynchronous.grid_file import (
)
from gridfs.errors import NoFile
from pymongo import AsyncMongoClient
from pymongo.asynchronous.helpers import aiter, anext
from pymongo.errors import ConfigurationError, ServerSelectionTimeoutError
from pymongo.message import _CursorAddress

View File

@ -36,8 +36,6 @@ from test.utils_shared import (
create_async_event,
)
from pymongo.asynchronous.helpers import anext
_IS_SYNC = False
pytestmark = pytest.mark.load_balancer

View File

@ -40,7 +40,6 @@ from bson.objectid import ObjectId
from bson.son import SON
from pymongo import CursorType, DeleteOne, InsertOne, UpdateOne, monitoring
from pymongo.asynchronous.command_cursor import AsyncCommandCursor
from pymongo.asynchronous.helpers import anext
from pymongo.errors import AutoReconnect, NotPrimaryError, OperationFailure
from pymongo.read_preferences import ReadPreference
from pymongo.write_concern import WriteConcern

View File

@ -42,7 +42,6 @@ from test.utils_shared import (
from test.version import Version
from bson.son import SON
from pymongo.asynchronous.helpers import anext
from pymongo.asynchronous.mongo_client import AsyncMongoClient
from pymongo.errors import ConfigurationError, OperationFailure
from pymongo.message import _maybe_add_read_preference

View File

@ -48,7 +48,6 @@ from gridfs.asynchronous.grid_file import AsyncGridFS, AsyncGridFSBucket
from pymongo import ASCENDING, AsyncMongoClient, _csot, monitoring
from pymongo.asynchronous.command_cursor import AsyncCommandCursor
from pymongo.asynchronous.cursor import AsyncCursor
from pymongo.asynchronous.helpers import anext
from pymongo.common import _MAX_END_SESSIONS
from pymongo.errors import ConfigurationError, InvalidOperation, OperationFailure
from pymongo.operations import IndexModel, InsertOne, UpdateOne

View File

@ -39,7 +39,6 @@ from pymongo.asynchronous import client_session
from pymongo.asynchronous.client_session import TransactionOptions
from pymongo.asynchronous.command_cursor import AsyncCommandCursor
from pymongo.asynchronous.cursor import AsyncCursor
from pymongo.asynchronous.helpers import anext
from pymongo.errors import (
AutoReconnect,
CollectionInvalid,

View File

@ -77,7 +77,6 @@ from pymongo.asynchronous.collection import AsyncCollection
from pymongo.asynchronous.command_cursor import AsyncCommandCursor
from pymongo.asynchronous.database import AsyncDatabase
from pymongo.asynchronous.encryption import AsyncClientEncryption
from pymongo.asynchronous.helpers import anext
from pymongo.driver_info import DriverInfo
from pymongo.encryption_options import _HAVE_PYMONGOCRYPT, AutoEncryptionOpts
from pymongo.errors import (

View File

@ -55,7 +55,6 @@ from pymongo.errors import (
from pymongo.message import _CursorAddress
from pymongo.read_concern import ReadConcern
from pymongo.synchronous.command_cursor import CommandCursor
from pymongo.synchronous.helpers import next
from pymongo.write_concern import WriteConcern
_IS_SYNC = True

View File

@ -114,7 +114,6 @@ from pymongo.server_type import SERVER_TYPE
from pymongo.synchronous.command_cursor import CommandCursor
from pymongo.synchronous.cursor import Cursor, CursorType
from pymongo.synchronous.database import Database
from pymongo.synchronous.helpers import next
from pymongo.synchronous.mongo_client import MongoClient
from pymongo.synchronous.pool import (
Connection,

View File

@ -37,7 +37,6 @@ from pymongo.operations import (
UpdateMany,
UpdateOne,
)
from pymongo.synchronous.helpers import next
from pymongo.write_concern import WriteConcern
_IS_SYNC = True

View File

@ -74,7 +74,6 @@ from pymongo.results import (
)
from pymongo.synchronous.collection import Collection, ReturnDocument
from pymongo.synchronous.command_cursor import CommandCursor
from pymongo.synchronous.helpers import next
from pymongo.synchronous.mongo_client import MongoClient
from pymongo.write_concern import WriteConcern

View File

@ -51,7 +51,6 @@ from pymongo.operations import _IndexList
from pymongo.read_concern import ReadConcern
from pymongo.read_preferences import ReadPreference
from pymongo.synchronous.cursor import Cursor, CursorType
from pymongo.synchronous.helpers import next
from pymongo.write_concern import WriteConcern
_IS_SYNC = True

View File

@ -55,7 +55,6 @@ from bson.raw_bson import RawBSONDocument
from pymongo.errors import DuplicateKeyError
from pymongo.message import _CursorAddress
from pymongo.synchronous.collection import ReturnDocument
from pymongo.synchronous.helpers import next
_IS_SYNC = True

View File

@ -51,7 +51,6 @@ from pymongo.read_preferences import ReadPreference
from pymongo.synchronous import auth
from pymongo.synchronous.collection import Collection
from pymongo.synchronous.database import Database
from pymongo.synchronous.helpers import next
from pymongo.synchronous.mongo_client import MongoClient
from pymongo.write_concern import WriteConcern

View File

@ -41,7 +41,6 @@ import pytest
from pymongo.daemon import _spawn_daemon
from pymongo.synchronous.collection import Collection
from pymongo.synchronous.helpers import next
from pymongo.uri_parser_shared import _parse_kms_tls_options
try:

View File

@ -33,7 +33,6 @@ from pymongo.errors import ConnectionFailure, OperationFailure
from pymongo.read_concern import ReadConcern
from pymongo.read_preferences import ReadPreference
from pymongo.server_api import ServerApi
from pymongo.synchronous.helpers import next
from pymongo.write_concern import WriteConcern
_IS_SYNC = True

View File

@ -49,7 +49,6 @@ from gridfs.synchronous.grid_file import (
from pymongo import MongoClient
from pymongo.errors import ConfigurationError, ServerSelectionTimeoutError
from pymongo.message import _CursorAddress
from pymongo.synchronous.helpers import iter, next
_IS_SYNC = True

View File

@ -36,8 +36,6 @@ from test.utils_shared import (
wait_until,
)
from pymongo.synchronous.helpers import next
_IS_SYNC = True
pytestmark = pytest.mark.load_balancer

View File

@ -42,7 +42,6 @@ from pymongo import CursorType, DeleteOne, InsertOne, UpdateOne, monitoring
from pymongo.errors import AutoReconnect, NotPrimaryError, OperationFailure
from pymongo.read_preferences import ReadPreference
from pymongo.synchronous.command_cursor import CommandCursor
from pymongo.synchronous.helpers import next
from pymongo.write_concern import WriteConcern
_IS_SYNC = True

View File

@ -56,7 +56,6 @@ from pymongo.read_preferences import (
from pymongo.server_description import ServerDescription
from pymongo.server_selectors import Selection, readable_server_selector
from pymongo.server_type import SERVER_TYPE
from pymongo.synchronous.helpers import next
from pymongo.synchronous.mongo_client import MongoClient
from pymongo.write_concern import WriteConcern

View File

@ -52,7 +52,6 @@ from pymongo.operations import IndexModel, InsertOne, UpdateOne
from pymongo.read_concern import ReadConcern
from pymongo.synchronous.command_cursor import CommandCursor
from pymongo.synchronous.cursor import Cursor
from pymongo.synchronous.helpers import next
_IS_SYNC = True

View File

@ -50,7 +50,6 @@ from pymongo.synchronous import client_session
from pymongo.synchronous.client_session import TransactionOptions
from pymongo.synchronous.command_cursor import CommandCursor
from pymongo.synchronous.cursor import Cursor
from pymongo.synchronous.helpers import next
_IS_SYNC = True

View File

@ -101,7 +101,6 @@ from pymongo.synchronous.collection import Collection
from pymongo.synchronous.command_cursor import CommandCursor
from pymongo.synchronous.database import Database
from pymongo.synchronous.encryption import ClientEncryption
from pymongo.synchronous.helpers import next
from pymongo.topology_description import TopologyDescription
from pymongo.typings import _Address
from pymongo.write_concern import WriteConcern