Skip to content

Commit d7074ba

Browse files
authored
PYTHON-5454 & PYTHON-5455 Add preliminary python 3.14 support (#2451)
1 parent d11cf20 commit d7074ba

File tree

9 files changed

+2184
-1602
lines changed

9 files changed

+2184
-1602
lines changed

.evergreen/generated_configs/tasks.yml

Lines changed: 695 additions & 422 deletions
Large diffs are not rendered by default.

.evergreen/generated_configs/variants.yml

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -292,32 +292,32 @@ buildvariants:
292292
AUTH: auth
293293

294294
# Free threaded tests
295-
- name: free-threaded-rhel8-python3.13t
295+
- name: free-threaded-rhel8-python3.14t
296296
tasks:
297297
- name: .free-threading
298-
display_name: Free-threaded RHEL8 Python3.13t
298+
display_name: Free-threaded RHEL8 Python3.14t
299299
run_on:
300300
- rhel87-small
301301
expansions:
302-
PYTHON_BINARY: /opt/python/3.13t/bin/python3
302+
PYTHON_BINARY: /opt/python/3.14t/bin/python3
303303
tags: [pr]
304-
- name: free-threaded-macos-python3.13t
304+
- name: free-threaded-macos-python3.14t
305305
tasks:
306306
- name: .free-threading
307-
display_name: Free-threaded macOS Python3.13t
307+
display_name: Free-threaded macOS Python3.14t
308308
run_on:
309309
- macos-14
310310
expansions:
311-
PYTHON_BINARY: /Library/Frameworks/PythonT.Framework/Versions/3.13/bin/python3t
311+
PYTHON_BINARY: /Library/Frameworks/PythonT.Framework/Versions/3.14/bin/python3t
312312
tags: []
313-
- name: free-threaded-macos-arm64-python3.13t
313+
- name: free-threaded-macos-arm64-python3.14t
314314
tasks:
315315
- name: .free-threading
316-
display_name: Free-threaded macOS Arm64 Python3.13t
316+
display_name: Free-threaded macOS Arm64 Python3.14t
317317
run_on:
318318
- macos-14-arm64
319319
expansions:
320-
PYTHON_BINARY: /Library/Frameworks/PythonT.Framework/Versions/3.13/bin/python3t
320+
PYTHON_BINARY: /Library/Frameworks/PythonT.Framework/Versions/3.14/bin/python3t
321321
tags: []
322322
- name: free-threaded-win64-python3.14t
323323
tasks:
@@ -332,24 +332,20 @@ buildvariants:
332332
# Green framework tests
333333
- name: green-eventlet-rhel8
334334
tasks:
335-
- name: .test-standard .standalone-noauth-nossl .python-3.9
335+
- name: .test-standard .standalone-noauth-nossl .python-3.9 .sync
336336
display_name: Green Eventlet RHEL8
337337
run_on:
338338
- rhel87-small
339339
expansions:
340340
GREEN_FRAMEWORK: eventlet
341-
AUTH: auth
342-
SSL: ssl
343341
- name: green-gevent-rhel8
344342
tasks:
345-
- name: .test-standard .standalone-noauth-nossl
343+
- name: .test-standard .standalone-noauth-nossl .sync
346344
display_name: Green Gevent RHEL8
347345
run_on:
348346
- rhel87-small
349347
expansions:
350348
GREEN_FRAMEWORK: gevent
351-
AUTH: auth
352-
SSL: ssl
353349

354350
# Import time tests
355351
- name: import-time

.evergreen/scripts/generate_config.py

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,7 @@ def create_standard_nonlinux_variants() -> list[BuildVariant]:
107107
def create_free_threaded_variants() -> list[BuildVariant]:
108108
variants = []
109109
for host_name in ("rhel8", "macos", "macos-arm64", "win64"):
110-
if host_name == "win64":
111-
python = "3.14t"
112-
else:
113-
python = "3.13t"
110+
python = "3.14t"
114111
tasks = [".free-threading"]
115112
tags = []
116113
if host_name == "rhel8":
@@ -300,12 +297,12 @@ def create_green_framework_variants():
300297
variants = []
301298
host = DEFAULT_HOST
302299
for framework in ["eventlet", "gevent"]:
303-
tasks = [".test-standard .standalone-noauth-nossl"]
300+
tasks = [".test-standard .standalone-noauth-nossl .sync"]
304301
if framework == "eventlet":
305302
# Eventlet has issues with dnspython > 2.0 and newer versions of CPython
306303
# https://jira.mongodb.org/browse/PYTHON-5284
307-
tasks = [".test-standard .standalone-noauth-nossl .python-3.9"]
308-
expansions = dict(GREEN_FRAMEWORK=framework, AUTH="auth", SSL="ssl")
304+
tasks = [".test-standard .standalone-noauth-nossl .python-3.9 .sync"]
305+
expansions = dict(GREEN_FRAMEWORK=framework)
309306
display_name = get_variant_name(f"Green {framework.capitalize()}", host)
310307
variant = create_variant(tasks, display_name, host=host, expansions=expansions)
311308
variants.append(variant)
@@ -636,20 +633,15 @@ def create_test_non_standard_tasks():
636633
def create_standard_tasks():
637634
"""For variants that do not set a TEST_NAME."""
638635
tasks = []
639-
task_combos = []
640-
# For each version and topology, rotate through the CPythons and sync/async.
641-
for (version, topology), python, sync in zip_cycle(
642-
list(product(ALL_VERSIONS, TOPOLOGIES)), CPYTHONS, SYNCS
643-
):
644-
pr = version == "latest"
645-
task_combos.append((version, topology, python, sync, pr))
646-
# For each PyPy and topology, rotate through the the versions and sync/async.
647-
for (python, topology), version, sync in zip_cycle(
648-
list(product(PYPYS, TOPOLOGIES)), ALL_VERSIONS, SYNCS
636+
task_combos = set()
637+
# For each python and topology and sync/async, rotate through the the versions.
638+
for (python, topology, sync), version in zip_cycle(
639+
list(product(CPYTHONS + PYPYS, TOPOLOGIES, SYNCS)), ALL_VERSIONS
649640
):
650-
task_combos.append((version, topology, python, sync, False))
641+
pr = version == "latest" and python not in PYPYS
642+
task_combos.add((version, topology, python, sync, pr))
651643

652-
for version, topology, python, sync, pr in task_combos:
644+
for version, topology, python, sync, pr in sorted(task_combos):
653645
auth, ssl = get_standard_auth_ssl(topology)
654646
tags = [
655647
"test-standard",

.evergreen/scripts/generate_config_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
##############
2323

2424
ALL_VERSIONS = ["4.2", "4.4", "5.0", "6.0", "7.0", "8.0", "rapid", "latest"]
25-
CPYTHONS = ["3.9", "3.10", "3.11", "3.12", "3.13"]
25+
CPYTHONS = ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
2626
PYPYS = ["pypy3.10"]
2727
ALL_PYTHONS = CPYTHONS + PYPYS
2828
MIN_MAX_PYTHON = [CPYTHONS[0], CPYTHONS[-1]]

doc/changelog.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ Changes in Version 4.14.0 (XXXX/XX/XX)
55
--------------------------------------
66
PyMongo 4.14 brings a number of changes including:
77

8+
- Added preliminary support for Python 3.14 and 3.14 with free-threading. We do not yet support the following with Python 3.14:
9+
- Subinterpreters (``concurrent.interpreters``)
10+
- Free-threading with Encryption
11+
- mod_wsgi
12+
- Removed experimental support for free-threading support in Python 3.13.
813
- Added :attr:`bson.codec_options.TypeRegistry.codecs` and :attr:`bson.codec_options.TypeRegistry.fallback_encoder` properties
914
to allow users to directly access the type codecs and fallback encoder for a given :class:`bson.codec_options.TypeRegistry`.
1015
- Added :meth:`pymongo.asynchronous.mongo_client.AsyncMongoClient.append_metadata` and

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ dev = [
5050
"pre-commit>=4.0"
5151
]
5252
pip = ["pip"]
53-
gevent = ["gevent"]
53+
# TODO: PYTHON-5464
54+
gevent = ["gevent", "cffi>=2.0.0b1;python_version=='3.14'"]
5455
eventlet = ["eventlet"]
5556
coverage = [
5657
"pytest-cov",

test/asynchronous/test_cursor.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,12 @@ async def test_explain_csot(self):
369369
client = await self.async_rs_or_single_client(event_listeners=[listener])
370370

371371
# Create a collection, referred to as collection, with the namespace explain-test.collection.
372-
collection = client["explain-test"]["collection"]
372+
# Workaround for SERVER-108463
373+
names = await client["explain-test"].list_collection_names()
374+
if "collection" not in names:
375+
collection = await client["explain-test"].create_collection("collection")
376+
else:
377+
collection = client["explain-test"]["collection"]
373378

374379
# Run an explained find on collection. The find will have the query predicate { name: 'john doe' }. Specify a maxTimeMS value of 2000ms for the explain.
375380
with pymongo.timeout(2.0):

test/test_cursor.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,12 @@ def test_explain_csot(self):
361361
client = self.rs_or_single_client(event_listeners=[listener])
362362

363363
# Create a collection, referred to as collection, with the namespace explain-test.collection.
364-
collection = client["explain-test"]["collection"]
364+
# Workaround for SERVER-108463
365+
names = client["explain-test"].list_collection_names()
366+
if "collection" not in names:
367+
collection = client["explain-test"].create_collection("collection")
368+
else:
369+
collection = client["explain-test"]["collection"]
365370

366371
# Run an explained find on collection. The find will have the query predicate { name: 'john doe' }. Specify a maxTimeMS value of 2000ms for the explain.
367372
with pymongo.timeout(2.0):

0 commit comments

Comments
 (0)