From 2f7b22160976d35c014f73e38f9f0e5b0399898b Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 16 Apr 2025 14:03:09 -0500 Subject: [PATCH 1/8] INTPYTHON-597 Convert no c extensions and doctests to use the standard test pattern --- .evergreen/generated_configs/functions.yml | 15 ------ .evergreen/generated_configs/tasks.yml | 9 ---- .evergreen/generated_configs/variants.yml | 53 +++------------------- .evergreen/scripts/generate_config.py | 39 ++++------------ .evergreen/scripts/run_tests.py | 7 +++ .evergreen/scripts/setup_tests.py | 3 ++ .evergreen/scripts/utils.py | 2 +- justfile | 4 -- 8 files changed, 27 insertions(+), 105 deletions(-) diff --git a/.evergreen/generated_configs/functions.yml b/.evergreen/generated_configs/functions.yml index bc8942efc5..06baa32e8d 100644 --- a/.evergreen/generated_configs/functions.yml +++ b/.evergreen/generated_configs/functions.yml @@ -85,21 +85,6 @@ functions: params: directory: src - # Run just script - run just script: - - command: subprocess.exec - params: - binary: bash - args: - - .evergreen/just.sh - - ${JUSTFILE_TARGET} - working_dir: src - include_expansions_in_env: - - AWS_ACCESS_KEY_ID - - AWS_SECRET_ACCESS_KEY - - AWS_SESSION_TOKEN - type: test - # Run server run server: - command: subprocess.exec diff --git a/.evergreen/generated_configs/tasks.yml b/.evergreen/generated_configs/tasks.yml index fddd725af6..4676ab80f3 100644 --- a/.evergreen/generated_configs/tasks.yml +++ b/.evergreen/generated_configs/tasks.yml @@ -734,15 +734,6 @@ tasks: depends_on: [{ name: .server-version, variant: .coverage_tag, status: "*", patch_optional: true }] tags: [coverage] - # Doctest tests - - name: test-doctests - commands: - - func: run server - - func: run just script - vars: - JUSTFILE_TARGET: docs-test - tags: [doctests] - # Enterprise auth tests - name: test-enterprise-auth-python3.9 commands: diff --git a/.evergreen/generated_configs/variants.yml b/.evergreen/generated_configs/variants.yml index d36548f72f..6dee0ac773 100644 --- a/.evergreen/generated_configs/variants.yml +++ b/.evergreen/generated_configs/variants.yml @@ -213,14 +213,14 @@ buildvariants: PYTHON_BINARY: /opt/python/3.9/bin/python3 # Doctests tests - - name: doctests-rhel8-python3.9 + - name: doctests-rhel8 tasks: - - name: .doctests - display_name: Doctests RHEL8 Python3.9 + - name: .standard-linux + display_name: Doctests RHEL8 run_on: - rhel87-small expansions: - PYTHON_BINARY: /opt/python/3.9/bin/python3 + TEST_NAME: doctest # Encryption tests - name: encryption-rhel8-python3.9 @@ -609,51 +609,12 @@ buildvariants: PYTHON_BINARY: /opt/python/3.13/bin/python3 # No c ext tests - - name: no-c-ext-rhel8-python3.9 - tasks: - - name: .standalone .noauth .nossl !.sync_async - display_name: No C Ext RHEL8 Python3.9 - run_on: - - rhel87-small - expansions: - NO_EXT: "1" - PYTHON_BINARY: /opt/python/3.9/bin/python3 - - name: no-c-ext-rhel8-python3.10 - tasks: - - name: .replica_set .noauth .nossl !.sync_async - display_name: No C Ext RHEL8 Python3.10 - run_on: - - rhel87-small - expansions: - NO_EXT: "1" - PYTHON_BINARY: /opt/python/3.10/bin/python3 - - name: no-c-ext-rhel8-python3.11 - tasks: - - name: .sharded_cluster .noauth .nossl !.sync_async - display_name: No C Ext RHEL8 Python3.11 - run_on: - - rhel87-small - expansions: - NO_EXT: "1" - PYTHON_BINARY: /opt/python/3.11/bin/python3 - - name: no-c-ext-rhel8-python3.12 + - name: no-c-ext-rhel8 tasks: - - name: .standalone .noauth .nossl !.sync_async - display_name: No C Ext RHEL8 Python3.12 - run_on: - - rhel87-small - expansions: - NO_EXT: "1" - PYTHON_BINARY: /opt/python/3.12/bin/python3 - - name: no-c-ext-rhel8-python3.13 - tasks: - - name: .replica_set .noauth .nossl !.sync_async - display_name: No C Ext RHEL8 Python3.13 + - name: .standard-linux + display_name: No C Ext RHEL8 run_on: - rhel87-small - expansions: - NO_EXT: "1" - PYTHON_BINARY: /opt/python/3.13/bin/python3 # No server tests - name: no-server diff --git a/.evergreen/scripts/generate_config.py b/.evergreen/scripts/generate_config.py index 7e88f82316..98774e5c5d 100644 --- a/.evergreen/scripts/generate_config.py +++ b/.evergreen/scripts/generate_config.py @@ -357,18 +357,12 @@ def create_green_framework_variants(): def create_no_c_ext_variants(): - variants = [] host = DEFAULT_HOST - for python, topology in zip_cycle(CPYTHONS, TOPOLOGIES): - tasks = [f".{topology} .noauth .nossl !.sync_async"] - expansions = dict() - handle_c_ext(C_EXTS[0], expansions) - display_name = get_variant_name("No C Ext", host, python=python) - variant = create_variant( - tasks, display_name, host=host, python=python, expansions=expansions - ) - variants.append(variant) - return variants + tasks = [".standard-linux"] + expansions = dict() + handle_c_ext(C_EXTS[0], expansions) + display_name = get_variant_name("No C Ext", host) + return [create_variant(tasks, display_name, host=host)] def create_atlas_data_lake_variants(): @@ -469,13 +463,13 @@ def create_mockupdb_variants(): def create_doctests_variants(): host = DEFAULT_HOST - python = CPYTHONS[0] + expansions = dict(TEST_NAME="doctest") return [ create_variant( - [".doctests"], - get_variant_name("Doctests", host, python=python), - python=python, + [".standard-linux"], + get_variant_name("Doctests", host), host=host, + expansions=expansions, ) ] @@ -1013,14 +1007,6 @@ def create_mockupdb_tasks(): return [EvgTask(name=task_name, tags=tags, commands=[test_func])] -def create_doctest_tasks(): - server_func = FunctionCall(func="run server") - test_func = FunctionCall(func="run just script", vars=dict(JUSTFILE_TARGET="docs-test")) - task_name = "test-doctests" - tags = ["doctests"] - return [EvgTask(name=task_name, tags=tags, commands=[server_func, test_func])] - - def create_no_server_tasks(): test_func = FunctionCall(func="run tests") task_name = "test-no-server" @@ -1164,13 +1150,6 @@ def create_run_server_func(): return "run server", [sub_cmd, expansion_cmd] -def create_run_just_script_func(): - includes = ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"] - args = [".evergreen/just.sh", "${JUSTFILE_TARGET}"] - cmd = get_subprocess_exec(include_expansions_in_env=includes, args=args) - return "run just script", [cmd] - - def create_run_tests_func(): includes = [ "AUTH", diff --git a/.evergreen/scripts/run_tests.py b/.evergreen/scripts/run_tests.py index 9f700d70e0..ae073c2666 100644 --- a/.evergreen/scripts/run_tests.py +++ b/.evergreen/scripts/run_tests.py @@ -152,6 +152,13 @@ def run() -> None: test_kms_send_to_remote(SUB_TEST_NAME) return + # Handle doctests. + if TEST_NAME == "doctest": + from sphinx.cmd.build import main + + result = main("-E -b doctest doc ./doc/_build/doctest".split()) + sys.exit(result) + # Send ecs tests to run remotely. if TEST_NAME == "auth_aws" and SUB_TEST_NAME == "ecs": run_command(f"{DRIVERS_TOOLS}/.evergreen/auth_aws/aws_setup.sh ecs") diff --git a/.evergreen/scripts/setup_tests.py b/.evergreen/scripts/setup_tests.py index bc9f97f1e2..bd307a4e10 100644 --- a/.evergreen/scripts/setup_tests.py +++ b/.evergreen/scripts/setup_tests.py @@ -285,6 +285,9 @@ def handle_test_env() -> None: write_env("GSSAPI_PORT", config["SASL_PORT"]) write_env("GSSAPI_PRINCIPAL", config["PRINCIPAL"]) + if test_name == "doctest": + UV_ARGS.append("--extra docs") + if test_name == "load_balancer": SINGLE_MONGOS_LB_URI = os.environ.get( "SINGLE_MONGOS_LB_URI", "mongodb://127.0.0.1:8000/?loadBalanced=true" diff --git a/.evergreen/scripts/utils.py b/.evergreen/scripts/utils.py index 214a1fc347..07207ae881 100644 --- a/.evergreen/scripts/utils.py +++ b/.evergreen/scripts/utils.py @@ -52,7 +52,7 @@ class Distro: # Tests that require a sub test suite. SUB_TEST_REQUIRED = ["auth_aws", "auth_oidc", "kms", "mod_wsgi", "perf"] -EXTRA_TESTS = ["mod_wsgi", "aws_lambda"] +EXTRA_TESTS = ["mod_wsgi", "aws_lambda", "doctest"] # Tests that do not use run-orchestration directly. NO_RUN_ORCHESTRATION = ["auth_oidc", "atlas_connect", "data_lake", "mockupdb", "serverless", "ocsp"] diff --git a/justfile b/justfile index 43aefb3f1a..74ebb48823 100644 --- a/justfile +++ b/justfile @@ -28,10 +28,6 @@ docs-serve: docs-linkcheck: {{docs_run}} sphinx-build -E -b linkcheck doc {{doc_build}}/linkcheck -[group('docs')] -docs-test: - {{docs_run}} --extra test sphinx-build -E -b doctest doc {{doc_build}}/doctest - [group('typing')] typing: just typing-mypy From f9a817991cd38ccfa717d12b7df3f55f0776b62e Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 16 Apr 2025 14:07:38 -0500 Subject: [PATCH 2/8] update start server options --- .evergreen/scripts/utils.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.evergreen/scripts/utils.py b/.evergreen/scripts/utils.py index 07207ae881..46e9821b48 100644 --- a/.evergreen/scripts/utils.py +++ b/.evergreen/scripts/utils.py @@ -55,7 +55,15 @@ class Distro: EXTRA_TESTS = ["mod_wsgi", "aws_lambda", "doctest"] # Tests that do not use run-orchestration directly. -NO_RUN_ORCHESTRATION = ["auth_oidc", "atlas_connect", "data_lake", "mockupdb", "serverless", "ocsp"] +NO_RUN_ORCHESTRATION = [ + "auth_oidc", + "atlas_connect", + "aws_lambda", + "data_lake", + "mockupdb", + "serverless", + "ocsp", +] def get_test_options( @@ -78,7 +86,7 @@ def get_test_options( else: parser.add_argument( "test_name", - choices=set(TEST_SUITE_MAP) - set(NO_RUN_ORCHESTRATION), + choices=set(TEST_SUITE_MAP) + set(EXTRA_TESTS) - set(NO_RUN_ORCHESTRATION), nargs="?", default="default", help="The optional name of the test suite to be run, which informs the server configuration.", From 974ebfa73042a850b8c8ba1aa786a8e09143f3fb Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 16 Apr 2025 14:09:58 -0500 Subject: [PATCH 3/8] fix choices --- .evergreen/scripts/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.evergreen/scripts/utils.py b/.evergreen/scripts/utils.py index 46e9821b48..bd93532600 100644 --- a/.evergreen/scripts/utils.py +++ b/.evergreen/scripts/utils.py @@ -86,7 +86,7 @@ def get_test_options( else: parser.add_argument( "test_name", - choices=set(TEST_SUITE_MAP) + set(EXTRA_TESTS) - set(NO_RUN_ORCHESTRATION), + choices=set(list(TEST_SUITE_MAP) + EXTRA_TESTS) - set(NO_RUN_ORCHESTRATION), nargs="?", default="default", help="The optional name of the test suite to be run, which informs the server configuration.", From 2ebf76bcf368da5df8c1079cb232aabd7b9d4680 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 16 Apr 2025 14:31:11 -0500 Subject: [PATCH 4/8] allow doctest to work on older server versions --- doc/conf.py | 1 + doc/examples/client_bulk.rst | 1 + 2 files changed, 2 insertions(+) diff --git a/doc/conf.py b/doc/conf.py index c3ee5d8900..5b906d351a 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -105,6 +105,7 @@ client = MongoClient() client.drop_database("doctest_test") db = client.doctest_test +server_major_version = int(client.server_info()['version'].split()[0]) """ # -- Options for HTML output --------------------------------------------------- diff --git a/doc/examples/client_bulk.rst b/doc/examples/client_bulk.rst index 447f09688f..86a805e769 100644 --- a/doc/examples/client_bulk.rst +++ b/doc/examples/client_bulk.rst @@ -2,6 +2,7 @@ Client Bulk Write Operations ============================= .. testsetup:: + :skipif: server_major_version < 8 from pymongo import MongoClient From a2ba6cb6e7f5d0d37d7a704cf10a2affca3ec8d1 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 16 Apr 2025 14:36:42 -0500 Subject: [PATCH 5/8] fix server version handling --- doc/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 5b906d351a..387b939344 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -105,7 +105,7 @@ client = MongoClient() client.drop_database("doctest_test") db = client.doctest_test -server_major_version = int(client.server_info()['version'].split()[0]) +server_major_version = int(client.server_info()['version'].split()[-1][0]) """ # -- Options for HTML output --------------------------------------------------- From 2b64885531601c7f93e673b4234f72f33c2f342a Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 16 Apr 2025 20:07:49 -0500 Subject: [PATCH 6/8] only noauth nossl for doctests --- .evergreen/generated_configs/variants.yml | 2 +- .evergreen/scripts/generate_config.py | 2 +- CONTRIBUTING.md | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.evergreen/generated_configs/variants.yml b/.evergreen/generated_configs/variants.yml index 6dee0ac773..0855a27636 100644 --- a/.evergreen/generated_configs/variants.yml +++ b/.evergreen/generated_configs/variants.yml @@ -215,7 +215,7 @@ buildvariants: # Doctests tests - name: doctests-rhel8 tasks: - - name: .standard-linux + - name: .standard-linux .standalone-noauth-nossl display_name: Doctests RHEL8 run_on: - rhel87-small diff --git a/.evergreen/scripts/generate_config.py b/.evergreen/scripts/generate_config.py index 98774e5c5d..b6bd5dce26 100644 --- a/.evergreen/scripts/generate_config.py +++ b/.evergreen/scripts/generate_config.py @@ -466,7 +466,7 @@ def create_doctests_variants(): expansions = dict(TEST_NAME="doctest") return [ create_variant( - [".standard-linux"], + [".standard-linux .standalone-noauth-nossl"], get_variant_name("Doctests", host), host=host, expansions=expansions, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 60583022b7..1125113681 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -294,7 +294,8 @@ Note: these tests can only be run from an Evergreen host. The doc tests require a running server. - Run `just run-server`. -- Run `just docs-test`. +- Run `just setup-tests doctest`. +- Run `just run-tests`. ### Free-threaded Python Tests From 7a4cbd8d031597258a36fca26ce1a03a7a035934 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 16 Apr 2025 21:00:51 -0500 Subject: [PATCH 7/8] update skips --- doc/examples/client_bulk.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/examples/client_bulk.rst b/doc/examples/client_bulk.rst index 86a805e769..ad435fa2e4 100644 --- a/doc/examples/client_bulk.rst +++ b/doc/examples/client_bulk.rst @@ -2,7 +2,6 @@ Client Bulk Write Operations ============================= .. testsetup:: - :skipif: server_major_version < 8 from pymongo import MongoClient @@ -47,6 +46,7 @@ summary of the types of operations performed in the bulk write, along with their .. doctest:: :options: +NORMALIZE_WHITESPACE + :skipif: server_major_version < 8 >>> from pymongo import InsertOne, DeleteOne, UpdateOne >>> models = [ @@ -80,6 +80,7 @@ instance will also include detailed results about each successful operation perf .. doctest:: :options: +NORMALIZE_WHITESPACE + :skipif: server_major_version < 8 >>> from pymongo import InsertOne, DeleteMany, ReplaceOne, UpdateMany >>> models = [ @@ -126,6 +127,7 @@ For example, a duplicate key error on the third operation below aborts the remai .. doctest:: :options: +NORMALIZE_WHITESPACE + :skipif: server_major_version < 8 >>> from pymongo import InsertOne, DeleteOne >>> from pymongo.errors import ClientBulkWriteException @@ -162,6 +164,7 @@ For example, the fourth and fifth write operations below get executed successful .. doctest:: :options: +NORMALIZE_WHITESPACE + :skipif: server_major_version < 8 >>> from pymongo import InsertOne, DeleteOne >>> from pymongo.errors import ClientBulkWriteException From 0edf817377802fee3c2891327e35a47e05ce2c1e Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 17 Apr 2025 07:49:51 -0500 Subject: [PATCH 8/8] fix workflow --- .github/workflows/test-python.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index 3c3eef989e..6d215bed0e 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -99,7 +99,9 @@ jobs: - name: Install dependencies run: just install - name: Run tests - run: just docs-test + run: | + just setup-tests doctest + just run-tests docs: name: Docs Checks