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

This commit is contained in:
Steven Silvester 2025-10-07 16:39:33 -05:00
commit c0b51913d2
No known key found for this signature in database
11 changed files with 475 additions and 39 deletions

View File

@ -4766,3 +4766,351 @@ tasks:
- standalone-noauth-nossl
- noauth
- pypy
# Test standard auth tests
- name: test-standard-auth-v4.2-python3.10-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "4.2"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "4.2"
PYTHON_VERSION: "3.10"
tags:
- test-standard-auth
- server-4.2
- python-3.10
- sharded_cluster-auth-ssl
- auth
- name: test-standard-auth-v4.2-pypy3.10-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "4.2"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "4.2"
PYTHON_VERSION: pypy3.10
tags:
- test-standard-auth
- server-4.2
- python-pypy3.10
- sharded_cluster-auth-ssl
- auth
- pypy
- name: test-standard-auth-v4.4-python3.11-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "4.4"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "4.4"
PYTHON_VERSION: "3.11"
tags:
- test-standard-auth
- server-4.4
- python-3.11
- sharded_cluster-auth-ssl
- auth
- name: test-standard-auth-v4.4-pypy3.10-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "4.4"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "4.4"
PYTHON_VERSION: pypy3.10
tags:
- test-standard-auth
- server-4.4
- python-pypy3.10
- sharded_cluster-auth-ssl
- auth
- pypy
- name: test-standard-auth-v5.0-python3.12-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "5.0"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "5.0"
PYTHON_VERSION: "3.12"
tags:
- test-standard-auth
- server-5.0
- python-3.12
- sharded_cluster-auth-ssl
- auth
- name: test-standard-auth-v5.0-pypy3.10-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "5.0"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "5.0"
PYTHON_VERSION: pypy3.10
tags:
- test-standard-auth
- server-5.0
- python-pypy3.10
- sharded_cluster-auth-ssl
- auth
- pypy
- name: test-standard-auth-v6.0-python3.13-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "6.0"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "6.0"
PYTHON_VERSION: "3.13"
tags:
- test-standard-auth
- server-6.0
- python-3.13
- sharded_cluster-auth-ssl
- auth
- name: test-standard-auth-v6.0-pypy3.10-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "6.0"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "6.0"
PYTHON_VERSION: pypy3.10
tags:
- test-standard-auth
- server-6.0
- python-pypy3.10
- sharded_cluster-auth-ssl
- auth
- pypy
- name: test-standard-auth-v7.0-python3.14t-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "7.0"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "7.0"
PYTHON_VERSION: 3.14t
tags:
- test-standard-auth
- server-7.0
- python-3.14t
- sharded_cluster-auth-ssl
- auth
- free-threaded
- name: test-standard-auth-v7.0-pypy3.10-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "7.0"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "7.0"
PYTHON_VERSION: pypy3.10
tags:
- test-standard-auth
- server-7.0
- python-pypy3.10
- sharded_cluster-auth-ssl
- auth
- pypy
- name: test-standard-auth-v8.0-python3.14-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "8.0"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "8.0"
PYTHON_VERSION: "3.14"
tags:
- test-standard-auth
- server-8.0
- python-3.14
- sharded_cluster-auth-ssl
- auth
- name: test-standard-auth-v8.0-pypy3.10-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "8.0"
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: "8.0"
PYTHON_VERSION: pypy3.10
tags:
- test-standard-auth
- server-8.0
- python-pypy3.10
- sharded_cluster-auth-ssl
- auth
- pypy
- name: test-standard-auth-latest-python3.11-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: latest
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: latest
PYTHON_VERSION: "3.11"
tags:
- test-standard-auth
- server-latest
- python-3.11
- sharded_cluster-auth-ssl
- auth
- pr
- name: test-standard-auth-latest-pypy3.10-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: latest
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: latest
PYTHON_VERSION: pypy3.10
tags:
- test-standard-auth
- server-latest
- python-pypy3.10
- sharded_cluster-auth-ssl
- auth
- pypy
- name: test-standard-auth-rapid-python3.10-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: rapid
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: rapid
PYTHON_VERSION: "3.10"
tags:
- test-standard-auth
- server-rapid
- python-3.10
- sharded_cluster-auth-ssl
- auth
- name: test-standard-auth-rapid-pypy3.10-auth-ssl-sharded-cluster
commands:
- func: run server
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: rapid
- func: run tests
vars:
AUTH: auth
SSL: ssl
TOPOLOGY: sharded_cluster
VERSION: rapid
PYTHON_VERSION: pypy3.10
tags:
- test-standard-auth
- server-rapid
- python-pypy3.10
- sharded_cluster-auth-ssl
- auth
- pypy

View File

@ -9,6 +9,7 @@ buildvariants:
batchtime: 1440
expansions:
VERSION: latest
PYTHON_BINARY: /usr/bin/python3.11
NO_EXT: "1"
REQUIRE_FIPS: "1"
tags: []
@ -21,6 +22,7 @@ buildvariants:
batchtime: 1440
expansions:
VERSION: latest
PYTHON_BINARY: /usr/bin/python3.11
NO_EXT: "1"
tags: []
- name: other-hosts-rhel8-power8-latest
@ -32,6 +34,7 @@ buildvariants:
batchtime: 1440
expansions:
VERSION: latest
PYTHON_BINARY: /usr/bin/python3.11
NO_EXT: "1"
tags: []
- name: other-hosts-rhel8-arm64-latest
@ -43,6 +46,7 @@ buildvariants:
batchtime: 1440
expansions:
VERSION: latest
PYTHON_BINARY: /usr/bin/python3.11
NO_EXT: "1"
tags: []
- name: other-hosts-amazon2023-latest
@ -54,6 +58,7 @@ buildvariants:
batchtime: 1440
expansions:
VERSION: latest
PYTHON_BINARY: /usr/bin/python3.11
NO_EXT: "1"
tags: [pr]
@ -71,7 +76,7 @@ buildvariants:
# Aws auth tests
- name: auth-aws-ubuntu-20
tasks:
- name: .auth-aws
- name: .auth-aws !.auth-aws-ecs
display_name: Auth AWS Ubuntu-20
run_on:
- ubuntu2004-small
@ -244,7 +249,7 @@ buildvariants:
# Enterprise auth tests
- name: auth-enterprise-rhel8
tasks:
- name: .test-non-standard .auth !.free-threaded
- name: .test-standard-auth .auth !.free-threaded
display_name: Auth Enterprise RHEL8
run_on:
- rhel87-small
@ -253,7 +258,7 @@ buildvariants:
AUTH: auth
- name: auth-enterprise-macos
tasks:
- name: .test-non-standard !.pypy .auth !.free-threaded
- name: .test-standard-auth !.pypy .auth !.free-threaded
display_name: Auth Enterprise macOS
run_on:
- macos-14
@ -262,7 +267,7 @@ buildvariants:
AUTH: auth
- name: auth-enterprise-win64
tasks:
- name: .test-non-standard !.pypy .auth
- name: .test-standard-auth !.pypy .auth
display_name: Auth Enterprise Win64
run_on:
- windows-64-vsMulti-small

View File

@ -202,12 +202,12 @@ def create_enterprise_auth_variants():
for host in ["rhel8", "macos", "win64"]:
expansions = dict(TEST_NAME="enterprise_auth", AUTH="auth")
display_name = get_variant_name("Auth Enterprise", host)
tasks = [".test-non-standard .auth !.free-threaded"]
tasks = [".test-standard-auth .auth !.free-threaded"]
# https://jira.mongodb.org/browse/PYTHON-5586
if host == "macos":
tasks = [".test-non-standard !.pypy .auth !.free-threaded"]
tasks = [".test-standard-auth !.pypy .auth !.free-threaded"]
if host == "win64":
tasks = [".test-non-standard !.pypy .auth"]
tasks = [".test-standard-auth !.pypy .auth"]
variant = create_variant(tasks, display_name, host=host, expansions=expansions)
variants.append(variant)
return variants
@ -438,7 +438,8 @@ def create_aws_auth_variants():
for host_name in ["ubuntu20", "win64", "macos"]:
expansions = dict()
tasks = [".auth-aws"]
# PYTHON-5604 - we need to skip ECS tests for now.
tasks = [".auth-aws !.auth-aws-ecs"]
tags = []
if host_name == "macos":
tasks = [".auth-aws !.auth-aws-web-identity !.auth-aws-ecs !.auth-aws-ec2"]
@ -469,7 +470,8 @@ def create_alternative_hosts_variants():
version = "latest"
for host_name in OTHER_HOSTS:
expansions = dict(VERSION="latest")
# Use explicit Python 3.11 binary on the host since the default python3 is 3.9.
expansions = dict(VERSION="latest", PYTHON_BINARY="/usr/bin/python3.11")
handle_c_ext(C_EXTS[0], expansions)
host = HOSTS[host_name]
tags = []
@ -574,7 +576,7 @@ def create_test_non_standard_tasks():
for (version, topology), python in zip_cycle(list(product(ALL_VERSIONS, TOPOLOGIES)), CPYTHONS):
pr = version == "latest"
task_combos.add((version, topology, python, pr))
# For each PyPy and topology, rotate through the the versions.
# For each PyPy and topology, rotate through the MongoDB versions.
for (python, topology), version in zip_cycle(list(product(PYPYS, TOPOLOGIES)), ALL_VERSIONS):
task_combos.add((version, topology, python, False))
for version, topology, python, pr in sorted(task_combos):
@ -602,6 +604,46 @@ def create_test_non_standard_tasks():
return tasks
def create_test_standard_auth_tasks():
"""We only use auth on sharded clusters"""
tasks = []
task_combos = set()
# Rotate through the CPython and MongoDB versions
for (version, topology), python in zip_cycle(
list(product(ALL_VERSIONS, ["sharded_cluster"])), CPYTHONS
):
pr = version == "latest"
task_combos.add((version, topology, python, pr))
# Rotate through each PyPy and MongoDB versions.
for (python, topology), version in zip_cycle(
list(product(PYPYS, ["sharded_cluster"])), ALL_VERSIONS
):
task_combos.add((version, topology, python, False))
for version, topology, python, pr in sorted(task_combos):
auth, ssl = get_standard_auth_ssl(topology)
tags = [
"test-standard-auth",
f"server-{version}",
f"python-{python}",
f"{topology}-{auth}-{ssl}",
auth,
]
if "t" in python:
tags.append("free-threaded")
if python in PYPYS:
tags.append("pypy")
if pr:
tags.append("pr")
expansions = dict(AUTH=auth, SSL=ssl, TOPOLOGY=topology, VERSION=version)
name = get_task_name("test-standard-auth", python=python, **expansions)
server_func = FunctionCall(func="run server", vars=expansions)
test_vars = expansions.copy()
test_vars["PYTHON_VERSION"] = python
test_func = FunctionCall(func="run tests", vars=test_vars)
tasks.append(EvgTask(name=name, tags=tags, commands=[server_func, test_func]))
return tasks
def create_min_deps_tasks():
"""For variants that support testing with minimum dependencies."""
tasks = []

38
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,38 @@
<!-- Thanks for contributing! -->
<!-- Please ensure that the title of the PR is in the following form:
[Issue Type]-[Issue Key]: Issue Title
If you are an external contributor and there is no JIRA ticket associated with your change, then use your best judgement
for the PR title. A MongoDB employee will create a JIRA ticket and edit the name and links as appropriate.
-->
[Issue Key](https://jira.mongodb.org/browse/%7BISSUE_KEY%7D)
## Summary
<!-- What conceptually is this PR introducing? If context is already provided from the JIRA ticket, still place it in the
Pull Request as you should not make the reviewer do digging for a basic summary. -->
## Changes in this PR
<!-- What changes did you make to the code? What new APIs (public or private) were added, removed, or edited to generate
the desired outcome explained in the above summary? -->
## Testing Plan
<!-- How did you test the code? If you added unit tests, you can say that. If you didnt introduce unit tests, explain why.
All code should be tested in some way so please list what your validation strategy was. -->
### Screenshots (optional)
<!-- Usually a great supplement to a test plan, especially if this requires local testing. -->
## Checklist
<!-- Do not delete the items provided on this checklist. -->
### Checklist for Author
- [ ] Did you update the changelog (if necessary)?
- [ ] Is the intention of the code captured in relevant tests?
- [ ] If there are new TODOs, has a related JIRA ticket been created?
### Checklist for Reviewer {@primary_reviewer}
- [ ] Does the title of the PR reference a JIRA Ticket?
- [ ] Do you fully understand the implementation? (Would you be comfortable explaining how this code works to someone else?)
- [ ] Have you checked for spelling & grammar errors?
- [ ] Is all relevant documentation (README or docstring) updated?
## Focus Areas for Reviewer (optional)
<!-- List any complex portion of code you believe needs additional scrutiny and explain why. -->

View File

@ -1,23 +0,0 @@
# [JIRA Ticket ID](Link to Ticket)
<!-- Please provide explicit URL link to the corresponding JIRA ticket. -->
# Summary
<!-- Please provide a high level overview of what changes have been made. -->
# Changes in this PR
<!-- Highlight any high level architecture changes if the summary doesn't already cover the scope. -->
# Test Plan
<!-- Talk through any unit tests added, and if this is a bug fix, please add repro steps in the event the fix needs to be verified. -->
# Screenshots (Optional)
<!-- Add a before and after picture to indicate changes. -->
# Callouts or Follow-up items (Optional)
<!-- Any additional info not already specified in the PR including but not limited to:
1. Potential stakeholders
2. Slack threads etc.
3. Implementation details that need additional oversight
4. Callouts on future tactics
-->

View File

@ -58,7 +58,7 @@ lint-manual *args="": && resync
[group('test')]
test *args="-v --durations=5 --maxfail=10": && resync
uvx --extra test pytest {{args}}
uv run --extra test pytest {{args}}
[group('test')]
run-tests *args: && resync

View File

@ -3143,7 +3143,7 @@ class AsyncCollection(common.BaseObject, Generic[_DocumentType]):
comment: Optional[Any] = None,
hint: Optional[_IndexKeyHint] = None,
**kwargs: Any,
) -> list[str]:
) -> list[Any]:
"""Get a list of distinct values for `key` among all documents
in this collection.

View File

@ -1063,7 +1063,7 @@ class AsyncCursor(Generic[_DocumentType]):
"""Explicitly close / kill this cursor."""
await self._die_lock()
async def distinct(self, key: str) -> list[str]:
async def distinct(self, key: str) -> list[Any]:
"""Get a list of distinct values for `key` among all documents
in the result set of this query.

View File

@ -3136,7 +3136,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
comment: Optional[Any] = None,
hint: Optional[_IndexKeyHint] = None,
**kwargs: Any,
) -> list[str]:
) -> list[Any]:
"""Get a list of distinct values for `key` among all documents
in this collection.

View File

@ -1061,7 +1061,7 @@ class Cursor(Generic[_DocumentType]):
"""Explicitly close / kill this cursor."""
self._die_lock()
def distinct(self, key: str) -> list[str]:
def distinct(self, key: str) -> list[Any]:
"""Get a list of distinct values for `key` among all documents
in the result set of this query.

View File

@ -69,7 +69,7 @@ sys.path[0:0] = [""]
from test import IntegrationTest, PyMongoTestCase, client_context
from bson import CodecOptions, decode, decode_all, decode_file_iter, decode_iter, encode
from bson import CodecOptions, ObjectId, decode, decode_all, decode_file_iter, decode_iter, encode
from bson.raw_bson import RawBSONDocument
from bson.son import SON
from pymongo import ASCENDING, MongoClient
@ -141,6 +141,32 @@ class TestPymongo(IntegrationTest):
docs = to_list(cursor)
self.assertTrue(docs)
def test_distinct(self) -> None:
self.coll.delete_many({})
self.coll.insert_many(
[
{"_id": None},
{"_id": 0},
{"_id": ""},
{"_id": ObjectId()},
{"_id": True},
]
)
def collection_distinct(
collection: Collection,
) -> list[None | int | str | ObjectId | bool]:
return collection.distinct("_id")
def cursor_distinct(
collection: Collection,
) -> list[None | int | str | ObjectId | bool]:
cursor = collection.find()
return cursor.distinct("_id")
collection_distinct(self.coll)
cursor_distinct(self.coll)
@only_type_check
def test_bulk_write(self) -> None:
self.coll.insert_one({})