PYTHON-4755 - Stop supporting and testing against Eventlet (#2557)

This commit is contained in:
Noah Stapp 2025-09-24 14:07:51 -04:00 committed by GitHub
parent 0049dc8896
commit 9e64ed1bd8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 17 additions and 63 deletions

View File

@ -319,14 +319,6 @@ buildvariants:
tags: [] tags: []
# Green framework tests # Green framework tests
- name: green-eventlet-rhel8
tasks:
- name: .test-standard .python-3.9 .sync
display_name: Green Eventlet RHEL8
run_on:
- rhel87-small
expansions:
GREEN_FRAMEWORK: eventlet
- name: green-gevent-rhel8 - name: green-gevent-rhel8
tasks: tasks:
- name: .test-standard .sync - name: .test-standard .sync

View File

@ -300,12 +300,8 @@ def create_stable_api_variants():
def create_green_framework_variants(): def create_green_framework_variants():
variants = [] variants = []
host = DEFAULT_HOST host = DEFAULT_HOST
for framework in ["eventlet", "gevent"]: for framework in ["gevent"]:
tasks = [".test-standard .sync"] tasks = [".test-standard .sync"]
if framework == "eventlet":
# Eventlet has issues with dnspython > 2.0 and newer versions of CPython
# https://jira.mongodb.org/browse/PYTHON-5284
tasks = [".test-standard .python-3.9 .sync"]
expansions = dict(GREEN_FRAMEWORK=framework) expansions = dict(GREEN_FRAMEWORK=framework)
display_name = get_variant_name(f"Green {framework.capitalize()}", host) display_name = get_variant_name(f"Green {framework.capitalize()}", host)
variant = create_variant(tasks, display_name, host=host, expansions=expansions) variant = create_variant(tasks, display_name, host=host, expansions=expansions)

View File

@ -67,13 +67,7 @@ def handle_perf(start_time: datetime):
def handle_green_framework() -> None: def handle_green_framework() -> None:
if GREEN_FRAMEWORK == "eventlet": if GREEN_FRAMEWORK == "gevent":
import eventlet
# https://github.com/eventlet/eventlet/issues/401
eventlet.sleep()
eventlet.monkey_patch()
elif GREEN_FRAMEWORK == "gevent":
from gevent import monkey from gevent import monkey
monkey.patch_all() monkey.patch_all()

View File

@ -104,7 +104,7 @@ def get_test_options(
parser.add_argument( parser.add_argument(
"--green-framework", "--green-framework",
nargs=1, nargs=1,
choices=["eventlet", "gevent"], choices=["gevent"],
help="Optional green framework to test against.", help="Optional green framework to test against.",
) )
parser.add_argument( parser.add_argument(

View File

@ -9,6 +9,8 @@ PyMongo 4.16 brings a number of changes including:
- Removed invalid documents from :class:`bson.errors.InvalidDocument` error messages as - Removed invalid documents from :class:`bson.errors.InvalidDocument` error messages as
doing so may leak sensitive user data. doing so may leak sensitive user data.
Instead, invalid documents are stored in :attr:`bson.errors.InvalidDocument.document`. Instead, invalid documents are stored in :attr:`bson.errors.InvalidDocument.document`.
- Removed support for Eventlet.
Eventlet is actively being sunset by its maintainers and has compatibility issues with PyMongo's dnspython dependency.
Changes in Version 4.15.1 (2025/09/16) Changes in Version 4.15.1 (2025/09/16)
-------------------------------------- --------------------------------------

View File

@ -628,7 +628,7 @@ class AsyncConnection:
# signals and throws KeyboardInterrupt into the current frame on the # signals and throws KeyboardInterrupt into the current frame on the
# main thread. # main thread.
# #
# But in Gevent and Eventlet, the polling mechanism (epoll, kqueue, # But in Gevent, the polling mechanism (epoll, kqueue,
# ..) is called in Python code, which experiences the signal as a # ..) is called in Python code, which experiences the signal as a
# KeyboardInterrupt from the start, rather than as an initial # KeyboardInterrupt from the start, rather than as an initial
# socket.error, so we catch that, close the socket, and reraise it. # socket.error, so we catch that, close the socket, and reraise it.

View File

@ -138,13 +138,11 @@ def _raise_connection_failure(
msg = msg_prefix + msg msg = msg_prefix + msg
if "configured timeouts" not in msg: if "configured timeouts" not in msg:
msg += format_timeout_details(timeout_details) msg += format_timeout_details(timeout_details)
if isinstance(error, socket.timeout): if (
raise NetworkTimeout(msg) from error isinstance(error, socket.timeout)
elif isinstance(error, SSLErrors) and "timed out" in str(error): or isinstance(error, SSLErrors)
# Eventlet does not distinguish TLS network timeouts from other and "timed out" in str(error)
# SSLErrors (https://github.com/eventlet/eventlet/issues/692). ):
# Luckily, we can work around this limitation because the phrase
# 'timed out' appears in all the timeout related SSLErrors raised.
raise NetworkTimeout(msg) from error raise NetworkTimeout(msg) from error
else: else:
raise AutoReconnect(msg) from error raise AutoReconnect(msg) from error

View File

@ -626,7 +626,7 @@ class Connection:
# signals and throws KeyboardInterrupt into the current frame on the # signals and throws KeyboardInterrupt into the current frame on the
# main thread. # main thread.
# #
# But in Gevent and Eventlet, the polling mechanism (epoll, kqueue, # But in Gevent, the polling mechanism (epoll, kqueue,
# ..) is called in Python code, which experiences the signal as a # ..) is called in Python code, which experiences the signal as a
# KeyboardInterrupt from the start, rather than as an initial # KeyboardInterrupt from the start, rather than as an initial
# socket.error, so we catch that, close the socket, and reraise it. # socket.error, so we catch that, close the socket, and reraise it.

View File

@ -52,7 +52,6 @@ dev = [
pip = ["pip"] pip = ["pip"]
# TODO: PYTHON-5464 # TODO: PYTHON-5464
gevent = ["gevent", "cffi>=2.0.0b1;python_version=='3.14'"] gevent = ["gevent", "cffi>=2.0.0b1;python_version=='3.14'"]
eventlet = ["eventlet"]
coverage = [ coverage = [
"pytest-cov", "pytest-cov",
"coverage>=5,<=7.10.6" "coverage>=5,<=7.10.6"
@ -113,15 +112,12 @@ filterwarnings = [
"module:.*WindowsSelectorEventLoopPolicy:DeprecationWarning", "module:.*WindowsSelectorEventLoopPolicy:DeprecationWarning",
"module:.*et_event_loop_policy:DeprecationWarning", "module:.*et_event_loop_policy:DeprecationWarning",
# TODO: Remove as part of PYTHON-3923. # TODO: Remove as part of PYTHON-3923.
"module:unclosed <eventlet.green.ssl.GreenSSLSocket:ResourceWarning",
"module:unclosed <socket.socket:ResourceWarning", "module:unclosed <socket.socket:ResourceWarning",
"module:unclosed <ssl.SSLSocket:ResourceWarning", "module:unclosed <ssl.SSLSocket:ResourceWarning",
"module:unclosed <socket object:ResourceWarning", "module:unclosed <socket object:ResourceWarning",
"module:unclosed transport:ResourceWarning", "module:unclosed transport:ResourceWarning",
# pytest-asyncio known issue: https://github.com/pytest-dev/pytest-asyncio/issues/724 # pytest-asyncio known issue: https://github.com/pytest-dev/pytest-asyncio/issues/724
"module:unclosed event loop:ResourceWarning", "module:unclosed event loop:ResourceWarning",
# https://github.com/eventlet/eventlet/issues/818
"module:please use dns.resolver.Resolver.resolve:DeprecationWarning",
# https://github.com/dateutil/dateutil/issues/1314 # https://github.com/dateutil/dateutil/issues/1314
"module:datetime.datetime.utc:DeprecationWarning", "module:datetime.datetime.utc:DeprecationWarning",
] ]

View File

@ -399,7 +399,7 @@ class TestClientSimple(AsyncEncryptionIntegrationTest):
) )
@unittest.skipIf( @unittest.skipIf(
is_greenthread_patched(), is_greenthread_patched(),
"gevent and eventlet do not support POSIX-style forking.", "gevent does not support POSIX-style forking.",
) )
@async_client_context.require_sync @async_client_context.require_sync
async def test_fork(self): async def test_fork(self):

View File

@ -399,7 +399,7 @@ class TestClientSimple(EncryptionIntegrationTest):
) )
@unittest.skipIf( @unittest.skipIf(
is_greenthread_patched(), is_greenthread_patched(),
"gevent and eventlet do not support POSIX-style forking.", "gevent does not support POSIX-style forking.",
) )
@client_context.require_sync @client_context.require_sync
def test_fork(self): def test_fork(self):

View File

@ -34,7 +34,7 @@ from bson.objectid import ObjectId
) )
@unittest.skipIf( @unittest.skipIf(
is_greenthread_patched(), is_greenthread_patched(),
"gevent and eventlet do not support POSIX-style forking.", "gevent does not support POSIX-style forking.",
) )
class TestFork(IntegrationTest): class TestFork(IntegrationTest):
def test_lock_client(self): def test_lock_client(self):

View File

@ -528,15 +528,8 @@ def gevent_monkey_patched():
return False return False
def eventlet_monkey_patched():
"""Check if eventlet's monkey patching is active."""
import threading
return threading.current_thread.__module__ == "eventlet.green.threading"
def is_greenthread_patched(): def is_greenthread_patched():
return gevent_monkey_patched() or eventlet_monkey_patched() return gevent_monkey_patched()
def parse_read_preference(pref): def parse_read_preference(pref):

19
uv.lock generated
View File

@ -697,19 +697,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" },
] ]
[[package]]
name = "eventlet"
version = "0.40.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "dnspython" },
{ name = "greenlet" },
]
sdist = { url = "https://files.pythonhosted.org/packages/bf/a3/500893510ad316fc571d116d407ea17d6007a8ecdb0a456badb66eee42ae/eventlet-0.40.2.tar.gz", hash = "sha256:42636c277f761d026905cd0ba0a11edec7600001be401d6ae7e9546559c8d8b0", size = 565548, upload-time = "2025-07-22T14:49:54.317Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b6/41/2e2d46f31ed22c1c147936145badb86e0e28ba7fe7d7a54aa69849a93a52/eventlet-0.40.2-py3-none-any.whl", hash = "sha256:590c67b982015bc6b753a5303f3ec7356bc7890a39efd65176179f0113f5d35e", size = 364228, upload-time = "2025-07-22T14:49:52.082Z" },
]
[[package]] [[package]]
name = "exceptiongroup" name = "exceptiongroup"
version = "1.3.0" version = "1.3.0"
@ -1277,9 +1264,6 @@ coverage = [
dev = [ dev = [
{ name = "pre-commit" }, { name = "pre-commit" },
] ]
eventlet = [
{ name = "eventlet" },
]
gevent = [ gevent = [
{ name = "cffi", version = "2.0.0b1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.14.*'" }, { name = "cffi", version = "2.0.0b1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.14.*'" },
{ name = "gevent" }, { name = "gevent" },
@ -1309,7 +1293,7 @@ requires-dist = [
{ name = "furo", marker = "extra == 'docs'", specifier = "==2025.7.19" }, { name = "furo", marker = "extra == 'docs'", specifier = "==2025.7.19" },
{ name = "importlib-metadata", marker = "python_full_version < '3.13' and extra == 'test'", specifier = ">=7.0" }, { name = "importlib-metadata", marker = "python_full_version < '3.13' and extra == 'test'", specifier = ">=7.0" },
{ name = "pykerberos", marker = "os_name != 'nt' and extra == 'gssapi'" }, { name = "pykerberos", marker = "os_name != 'nt' and extra == 'gssapi'" },
{ name = "pymongo-auth-aws", marker = "extra == 'aws'", specifier = ">=1.1.1,<2.0.0" }, { name = "pymongo-auth-aws", marker = "extra == 'aws'", specifier = ">=1.1.0,<2.0.0" },
{ name = "pymongo-auth-aws", marker = "extra == 'encryption'", specifier = ">=1.1.0,<2.0.0" }, { name = "pymongo-auth-aws", marker = "extra == 'encryption'", specifier = ">=1.1.0,<2.0.0" },
{ name = "pymongocrypt", marker = "extra == 'encryption'", specifier = ">=1.13.0,<2.0.0" }, { name = "pymongocrypt", marker = "extra == 'encryption'", specifier = ">=1.13.0,<2.0.0" },
{ name = "pyopenssl", marker = "extra == 'ocsp'", specifier = ">=17.2.0" }, { name = "pyopenssl", marker = "extra == 'ocsp'", specifier = ">=17.2.0" },
@ -1334,7 +1318,6 @@ coverage = [
{ name = "pytest-cov" }, { name = "pytest-cov" },
] ]
dev = [{ name = "pre-commit", specifier = ">=4.0" }] dev = [{ name = "pre-commit", specifier = ">=4.0" }]
eventlet = [{ name = "eventlet" }]
gevent = [ gevent = [
{ name = "cffi", marker = "python_full_version == '3.14.*'", specifier = ">=2.0.0b1" }, { name = "cffi", marker = "python_full_version == '3.14.*'", specifier = ">=2.0.0b1" },
{ name = "gevent" }, { name = "gevent" },