From a2e39ada00a099d7dff2e69eb3b63461a9498d2a Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 7 Oct 2025 11:04:16 -0500 Subject: [PATCH 1/5] PYTHON-5596 Fix return type for distinct methods (#2576) --- justfile | 2 +- pymongo/asynchronous/collection.py | 2 +- pymongo/asynchronous/cursor.py | 2 +- pymongo/synchronous/collection.py | 2 +- pymongo/synchronous/cursor.py | 2 +- test/test_typing.py | 28 +++++++++++++++++++++++++++- 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/justfile b/justfile index f23534616..17b95e87b 100644 --- a/justfile +++ b/justfile @@ -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 diff --git a/pymongo/asynchronous/collection.py b/pymongo/asynchronous/collection.py index 6af1f4f78..e7e2f5803 100644 --- a/pymongo/asynchronous/collection.py +++ b/pymongo/asynchronous/collection.py @@ -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. diff --git a/pymongo/asynchronous/cursor.py b/pymongo/asynchronous/cursor.py index cf3a5372b..f19d3f6ce 100644 --- a/pymongo/asynchronous/cursor.py +++ b/pymongo/asynchronous/cursor.py @@ -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. diff --git a/pymongo/synchronous/collection.py b/pymongo/synchronous/collection.py index b68e4befe..4e5f7d08f 100644 --- a/pymongo/synchronous/collection.py +++ b/pymongo/synchronous/collection.py @@ -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. diff --git a/pymongo/synchronous/cursor.py b/pymongo/synchronous/cursor.py index 12e2863bc..fcd8ebeb1 100644 --- a/pymongo/synchronous/cursor.py +++ b/pymongo/synchronous/cursor.py @@ -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. diff --git a/test/test_typing.py b/test/test_typing.py index 7240e59c0..17dc21b4e 100644 --- a/test/test_typing.py +++ b/test/test_typing.py @@ -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({}) From 84772bd8a91a3278858be4fb7a2315a3df107bc2 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 7 Oct 2025 11:07:44 -0500 Subject: [PATCH 2/5] PYTHON-5604 Skip ECS tests until we can test on Ubuntu 22 (#2582) --- .evergreen/generated_configs/variants.yml | 2 +- .evergreen/scripts/generate_config.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.evergreen/generated_configs/variants.yml b/.evergreen/generated_configs/variants.yml index acdbd0dca..2fa66db21 100644 --- a/.evergreen/generated_configs/variants.yml +++ b/.evergreen/generated_configs/variants.yml @@ -71,7 +71,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 diff --git a/.evergreen/scripts/generate_config.py b/.evergreen/scripts/generate_config.py index 203f28830..051c0c866 100644 --- a/.evergreen/scripts/generate_config.py +++ b/.evergreen/scripts/generate_config.py @@ -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"] From 491f5ba77f7d280c3c5c39d313409de713b49daa Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 7 Oct 2025 12:30:06 -0500 Subject: [PATCH 3/5] PYTHON-5588 Fix python binary used in FIPS tests (#2581) --- .evergreen/generated_configs/variants.yml | 5 +++++ .evergreen/scripts/generate_config.py | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.evergreen/generated_configs/variants.yml b/.evergreen/generated_configs/variants.yml index 2fa66db21..0c46898c6 100644 --- a/.evergreen/generated_configs/variants.yml +++ b/.evergreen/generated_configs/variants.yml @@ -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] diff --git a/.evergreen/scripts/generate_config.py b/.evergreen/scripts/generate_config.py index 051c0c866..36cb02659 100644 --- a/.evergreen/scripts/generate_config.py +++ b/.evergreen/scripts/generate_config.py @@ -470,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 = [] From 89a4eaa36cb2694bb34f3ba796b14eb14776b0fa Mon Sep 17 00:00:00 2001 From: Iris <58442094+sleepyStick@users.noreply.github.com> Date: Tue, 7 Oct 2025 12:34:56 -0700 Subject: [PATCH 4/5] PYTHON-5576: add PR template to mongo-python-driver (#2567) --- .github/pull_request_template.md | 38 ++++++++++++++++++++++ .github/workflows/pull_request_template.md | 23 ------------- 2 files changed, 38 insertions(+), 23 deletions(-) create mode 100644 .github/pull_request_template.md delete mode 100644 .github/workflows/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..8185a3883 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,38 @@ + + +[Issue Key](https://jira.mongodb.org/browse/%7BISSUE_KEY%7D) +## Summary + + +## Changes in this PR + + +## Testing Plan + + +### Screenshots (optional) + + +## 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) + diff --git a/.github/workflows/pull_request_template.md b/.github/workflows/pull_request_template.md deleted file mode 100644 index 852066d4b..000000000 --- a/.github/workflows/pull_request_template.md +++ /dev/null @@ -1,23 +0,0 @@ -# [JIRA Ticket ID](Link to Ticket) - - -# Summary - - -# Changes in this PR - - -# Test Plan - - -# Screenshots (Optional) - - -# Callouts or Follow-up items (Optional) - From d59591311777f954470c77e8ea363d6695c03496 Mon Sep 17 00:00:00 2001 From: Casey Clements Date: Tue, 7 Oct 2025 15:43:07 -0400 Subject: [PATCH 5/5] PYTHON-5598 Add generate_config method to ensure auth is tested on free-threaded python 3.14t (#2580) --- .evergreen/generated_configs/tasks.yml | 348 ++++++++++++++++++++++ .evergreen/generated_configs/variants.yml | 6 +- .evergreen/scripts/generate_config.py | 48 ++- 3 files changed, 395 insertions(+), 7 deletions(-) diff --git a/.evergreen/generated_configs/tasks.yml b/.evergreen/generated_configs/tasks.yml index 8064ec85e..855cbefef 100644 --- a/.evergreen/generated_configs/tasks.yml +++ b/.evergreen/generated_configs/tasks.yml @@ -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 diff --git a/.evergreen/generated_configs/variants.yml b/.evergreen/generated_configs/variants.yml index 0c46898c6..aae221adf 100644 --- a/.evergreen/generated_configs/variants.yml +++ b/.evergreen/generated_configs/variants.yml @@ -249,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 @@ -258,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 @@ -267,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 diff --git a/.evergreen/scripts/generate_config.py b/.evergreen/scripts/generate_config.py index 36cb02659..7f199d148 100644 --- a/.evergreen/scripts/generate_config.py +++ b/.evergreen/scripts/generate_config.py @@ -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 @@ -576,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): @@ -604,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 = []