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
92 changes: 92 additions & 0 deletions .evergreen/generated_configs/tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,98 @@ tasks:
TEST_MIN_DEPS: "1"
tags: [test-min-deps, sharded_cluster-auth-ssl]

# Min support tests
- name: test-min-support-python3.9-standalone-noauth-nossl
commands:
- func: run server
- func: run tests
vars:
UV_PYTHON: "3.9"
AUTH: noauth
SSL: nossl
TOPOLOGY: standalone
tags: [test-min-support]
- name: test-min-support-python3.9-replica-set-noauth-ssl
commands:
- func: run server
- func: run tests
vars:
UV_PYTHON: "3.9"
AUTH: noauth
SSL: ssl
TOPOLOGY: replica_set
tags: [test-min-support]
- name: test-min-support-python3.9-sharded-cluster-auth-ssl
commands:
- func: run server
- func: run tests
vars:
UV_PYTHON: "3.9"
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
tags: [test-min-support]
- name: test-min-support-pypy3.9-standalone-noauth-nossl
commands:
- func: run server
- func: run tests
vars:
UV_PYTHON: pypy3.9
AUTH: noauth
SSL: nossl
TOPOLOGY: standalone
tags: [test-min-support]
- name: test-min-support-pypy3.9-replica-set-noauth-ssl
commands:
- func: run server
- func: run tests
vars:
UV_PYTHON: pypy3.9
AUTH: noauth
SSL: ssl
TOPOLOGY: replica_set
tags: [test-min-support]
- name: test-min-support-pypy3.9-sharded-cluster-auth-ssl
commands:
- func: run server
- func: run tests
vars:
UV_PYTHON: pypy3.9
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
tags: [test-min-support]
- name: test-min-support-pypy3.10-standalone-noauth-nossl
commands:
- func: run server
- func: run tests
vars:
UV_PYTHON: pypy3.10
AUTH: noauth
SSL: nossl
TOPOLOGY: standalone
tags: [test-min-support]
- name: test-min-support-pypy3.10-replica-set-noauth-ssl
commands:
- func: run server
- func: run tests
vars:
UV_PYTHON: pypy3.10
AUTH: noauth
SSL: ssl
TOPOLOGY: replica_set
tags: [test-min-support]
- name: test-min-support-pypy3.10-sharded-cluster-auth-ssl
commands:
- func: run server
- func: run tests
vars:
UV_PYTHON: pypy3.10
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
tags: [test-min-support]

# Mod wsgi tests
- name: mod-wsgi-replica-set-python3.10
commands:
Expand Down
8 changes: 8 additions & 0 deletions .evergreen/generated_configs/variants.yml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,14 @@ buildvariants:
expansions:
TEST_NAME: load_balancer

# Min support tests
- name: min-support-rhel8
tasks:
- name: .test-min-support
display_name: Min Support RHEL8
run_on:
- rhel87-small

# Mockupdb tests
- name: mockupdb-rhel8
tasks:
Expand Down
24 changes: 24 additions & 0 deletions .evergreen/scripts/generate_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,12 @@ def create_aws_auth_variants():
return variants


def create_min_support_variants():
host = HOSTS["rhel8"]
name = get_variant_name("Min Support", host=host)
return [create_variant([".test-min-support"], name, host=host)]


def create_no_server_variants():
host = HOSTS["rhel8"]
name = get_variant_name("No server", host=host)
Expand Down Expand Up @@ -897,6 +903,24 @@ def _create_ocsp_tasks(algo, variant, server_type, base_task_name):
return tasks


def create_min_support_tasks():
server_func = FunctionCall(func="run server")
from generate_config_utils import MIN_SUPPORT_VERSIONS

tasks = []
for python, topology in product(MIN_SUPPORT_VERSIONS, TOPOLOGIES):
auth, ssl = get_standard_auth_ssl(topology)
vars = dict(UV_PYTHON=python, AUTH=auth, SSL=ssl, TOPOLOGY=topology)
test_func = FunctionCall(func="run tests", vars=vars)
task_name = get_task_name(
"test-min-support", python=python, topology=topology, auth=auth, ssl=ssl
)
tags = ["test-min-support"]
commands = [server_func, test_func]
tasks.append(EvgTask(name=task_name, tags=tags, commands=commands))
return tasks


def create_aws_lambda_tasks():
assume_func = FunctionCall(func="assume ec2 role")
vars = dict(TEST_NAME="aws_lambda")
Expand Down
1 change: 1 addition & 0 deletions .evergreen/scripts/generate_config_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
ALL_VERSIONS = ["4.2", "4.4", "5.0", "6.0", "7.0", "8.0", "rapid", "latest"]
CPYTHONS = ["3.10", "3.11", "3.12", "3.13", "3.14t", "3.14"]
PYPYS = ["pypy3.11"]
MIN_SUPPORT_VERSIONS = ["3.9", "pypy3.9", "pypy3.10"]
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to test against pypy3.10 as well?

Copy link
Member Author

Choose a reason for hiding this comment

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

It felt odd to leave it out, putting it in the bucket of EoL versions that should still work.

ALL_PYTHONS = CPYTHONS + PYPYS
MIN_MAX_PYTHON = [CPYTHONS[0], CPYTHONS[-1]]
BATCHTIME_WEEK = 10080
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/dist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ jobs:
- 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
Expand Down Expand Up @@ -110,7 +111,7 @@ jobs:
- uses: actions/setup-python@v6
with:
# Build sdist on lowest supported Python
python-version: "3.10"
python-version: "3.9"

- name: Build SDist
run: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ jobs:
cache: 'pip'
cache-dependency-path: 'pyproject.toml'
# Build sdist on lowest supported Python
python-version: "3.10"
python-version: "3.9"
- name: Build SDist
shell: bash
run: |
Expand Down Expand Up @@ -242,7 +242,7 @@ jobs:
cache: 'pip'
cache-dependency-path: 'sdist/test/pyproject.toml'
# Test sdist on lowest supported Python
python-version: "3.10"
python-version: "3.9"
- id: setup-mongodb
uses: mongodb-labs/drivers-evergreen-tools@master
- name: Run connect test from sdist
Expand All @@ -266,7 +266,7 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7
with:
python-version: "3.10"
python-version: "3.9"
- id: setup-mongodb
uses: mongodb-labs/drivers-evergreen-tools@master
with:
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ be of interest or that has already been addressed.

## Supported Interpreters

PyMongo supports CPython 3.10+ and PyPy3.10+. Language features not
PyMongo supports CPython 3.9+ and PyPy3.9+. Language features not
supported by all interpreters can not be used.

## Style Guide
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ package that is incompatible with PyMongo.

## Dependencies

PyMongo supports CPython 3.10+ and PyPy3.10+.
PyMongo supports CPython 3.9+ and PyPy3.9+.

Required dependencies:

Expand Down
7 changes: 2 additions & 5 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ 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 and PyPy 3.10: Python 3.10+ or PyPy 3.11+ is now required.

- Dropped support for Python 3.9 and PyPy 3.10.
- 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`.
- PyMongo now requires ``dnspython>=2.6.1``, since ``dnspython`` 1.0 is no longer maintained and is incompatible with
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>`_.
- PyMongo now requires ``dnspython>=2.6.1``, since ``dnspython`` 1.0 is no longer maintained.
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.
Expand Down
1 change: 1 addition & 0 deletions gridfs/asynchronous/grid_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
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,
Expand Down
1 change: 1 addition & 0 deletions gridfs/synchronous/grid_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
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

Expand Down
1 change: 1 addition & 0 deletions pymongo/asynchronous/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
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,
Expand Down
16 changes: 16 additions & 0 deletions pymongo/asynchronous/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
from __future__ import annotations

import asyncio
import builtins
import socket
import sys
from typing import (
Any,
Callable,
Expand Down Expand Up @@ -84,3 +86,17 @@ 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__()
Comment on lines +89 to +102
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we make "Drop 3.9 support" a python ticket? (Or re-open it?)

Copy link
Member Author

Choose a reason for hiding this comment

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

1 change: 1 addition & 0 deletions pymongo/synchronous/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
_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

Expand Down
16 changes: 16 additions & 0 deletions pymongo/synchronous/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
from __future__ import annotations

import asyncio
import builtins
import socket
import sys
from typing import (
Any,
Callable,
Expand Down Expand Up @@ -84,3 +86,17 @@ 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__()
1 change: 1 addition & 0 deletions test/asynchronous/test_change_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
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,
Expand Down
1 change: 1 addition & 0 deletions test/asynchronous/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
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,
Expand Down
1 change: 1 addition & 0 deletions test/asynchronous/test_collation.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from test.utils_shared import EventListener, OvertCommandListener
from typing import Any

from pymongo.asynchronous.helpers import anext
from pymongo.collation import (
Collation,
CollationAlternate,
Expand Down
1 change: 1 addition & 0 deletions test/asynchronous/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from typing import Any, Iterable, no_type_check

from pymongo.asynchronous.database import AsyncDatabase
from pymongo.asynchronous.helpers import anext

sys.path[0:0] = [""]

Expand Down
1 change: 1 addition & 0 deletions test/asynchronous/test_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
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
Expand Down
1 change: 1 addition & 0 deletions test/asynchronous/test_custom_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
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

Expand Down
1 change: 1 addition & 0 deletions test/asynchronous/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
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,
Expand Down
1 change: 1 addition & 0 deletions test/asynchronous/test_encryption.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
from pymongo import ReadPreference
from pymongo.asynchronous import encryption
from pymongo.asynchronous.encryption import Algorithm, AsyncClientEncryption, QueryType
from pymongo.asynchronous.helpers import anext
from pymongo.asynchronous.mongo_client import AsyncMongoClient
from pymongo.cursor_shared import CursorType
from pymongo.encryption_options import _HAVE_PYMONGOCRYPT, AutoEncryptionOpts, RangeOpts, TextOpts
Expand Down
1 change: 1 addition & 0 deletions test/asynchronous/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
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
Expand Down
Loading
Loading