From d93d529eab5df6c5e4ef60b815dee55edd00c7a5 Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Tue, 27 Oct 2026 19:51:29 -0400 Subject: [PATCH] test: ignore pytest-asyncio loop scope deprecation warning under pytest 9.2 --- .../firestore-integration.yaml | 10 +--- packages/db-dtypes/pytest.ini | 3 +- packages/google-api-core/pyproject.toml | 1 + packages/google-auth-httplib2/pytest.ini | 2 + packages/google-cloud-core/pytest.ini | 1 + packages/google-cloud-dns/pytest.ini | 1 + .../pytest.ini | 1 + .../google-cloud-error-reporting/pytest.ini | 1 + packages/google-cloud-firestore/noxfile.py | 4 +- packages/google-cloud-firestore/pytest.ini | 4 +- .../tests/system/test_pipeline_acceptance.py | 15 +----- .../tests/system/test_system_async.py | 25 +++------- .../tests/unit/v1/test_base_client.py | 3 +- .../tests/unit/v1/test_bundle.py | 50 ++++++++++++------- packages/google-cloud-logging/pytest.ini | 1 + packages/google-cloud-pubsub/pytest.ini | 2 +- .../google-cloud-runtimeconfig/pytest.ini | 1 + packages/google-cloud-testutils/pytest.ini | 1 + packages/proto-plus/pytest.ini | 1 + 19 files changed, 62 insertions(+), 65 deletions(-) diff --git a/.librarian/generator-input/client-post-processing/firestore-integration.yaml b/.librarian/generator-input/client-post-processing/firestore-integration.yaml index 50defa6a4829..7ede6748b653 100644 --- a/.librarian/generator-input/client-post-processing/firestore-integration.yaml +++ b/.librarian/generator-input/client-post-processing/firestore-integration.yaml @@ -647,14 +647,6 @@ replacements: "pytest-xdist", ] count: 1 - - paths: [ - packages/google-cloud-firestore/noxfile.py - ] - before: | - "pytest-asyncio", - after: | - "pytest-asyncio==0.21.2", - count: 2 # TODO(https://github.com/googleapis/google-cloud-python/issues/17429): # Temporary post-processing rule to inject `-n auto` for Firestore parallel tests. # This rule should be removed once the generator template changes are released @@ -797,4 +789,4 @@ replacements: Code samples and snippets live in the `python-docs-samples`_ repo. .. _`python-docs-samples`: https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/firestore - count: 1 \ No newline at end of file + count: 1 diff --git a/packages/db-dtypes/pytest.ini b/packages/db-dtypes/pytest.ini index dbe13ba38624..23712a54a4cb 100644 --- a/packages/db-dtypes/pytest.ini +++ b/packages/db-dtypes/pytest.ini @@ -4,4 +4,5 @@ filterwarnings = error # Remove once https://github.com/googleapis/python-db-dtypes-pandas/issues/227 is fixed ignore:.*any.*with datetime64 dtypes is deprecated and will raise in a future version:FutureWarning - ignore:.*all.*with datetime64 dtypes is deprecated and will raise in a future version:FutureWarning + ignore:.*all.*with datetime64 dtypes is deprecated and will raise in a future version:FutureWarning + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning diff --git a/packages/google-api-core/pyproject.toml b/packages/google-api-core/pyproject.toml index b281b6b5d66e..46784ef87cd7 100644 --- a/packages/google-api-core/pyproject.toml +++ b/packages/google-api-core/pyproject.toml @@ -101,4 +101,5 @@ filterwarnings = [ "ignore:.*custom tp_new.*in Python 3.14:DeprecationWarning", # Remove once https://github.com/grpc/grpc/issues/35086 is fixed (and version newer than 1.60.0 is published) "ignore:There is no current event loop:DeprecationWarning", + "ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning", ] diff --git a/packages/google-auth-httplib2/pytest.ini b/packages/google-auth-httplib2/pytest.ini index 884da0e55a80..fdbdd34d6c3d 100644 --- a/packages/google-auth-httplib2/pytest.ini +++ b/packages/google-auth-httplib2/pytest.ini @@ -4,3 +4,5 @@ filterwarnings = error ignore:.*Please upgrade to the latest Python version.*:FutureWarning ignore:(?s).*using a Python version.*past its end of life.*:FutureWarning + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning + ignore:.*Module-scoped fixtures defined as instance methods are deprecated.*:pytest.PytestDeprecationWarning diff --git a/packages/google-cloud-core/pytest.ini b/packages/google-cloud-core/pytest.ini index 06dab82feb88..6fdedf71932f 100644 --- a/packages/google-cloud-core/pytest.ini +++ b/packages/google-cloud-core/pytest.ini @@ -10,3 +10,4 @@ filterwarnings = # Remove after support for Python 3.10+ is dropped ignore:\s*You are using a (non-supported )?Python version \(?3\.(8|9|1[0-9]+):DeprecationWarning ignore:\s*You are using a (non-supported )?Python version \(?3\.(8|9|1[0-9]+):FutureWarning + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning diff --git a/packages/google-cloud-dns/pytest.ini b/packages/google-cloud-dns/pytest.ini index d8732de43181..cdb8286ed1a7 100644 --- a/packages/google-cloud-dns/pytest.ini +++ b/packages/google-cloud-dns/pytest.ini @@ -12,3 +12,4 @@ filterwarnings = # Remove after support for Python 3.8, 3.9 and/or 3.10+ is dropped ignore:\s*You are using a (non-supported )?Python version \(?3\.(8|9|1[0-9]+):DeprecationWarning ignore:\s*You are using a (non-supported )?Python version \(?3\.(8|9|1[0-9]+):FutureWarning + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning diff --git a/packages/google-cloud-documentai-toolbox/pytest.ini b/packages/google-cloud-documentai-toolbox/pytest.ini index 4c9881c039ca..6a431f2c08de 100644 --- a/packages/google-cloud-documentai-toolbox/pytest.ini +++ b/packages/google-cloud-documentai-toolbox/pytest.ini @@ -18,3 +18,4 @@ filterwarnings = # Python 3.15 base64.urlsafe_b64decode emits FutureWarning when protobuf json_format # decodes standard base64 bytes fields containing '+' or '/' ignore:invalid character .* in URL-safe Base64 data will be discarded in future Python versions:FutureWarning + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning diff --git a/packages/google-cloud-error-reporting/pytest.ini b/packages/google-cloud-error-reporting/pytest.ini index 526706f7dfe2..cb6a12dff070 100644 --- a/packages/google-cloud-error-reporting/pytest.ini +++ b/packages/google-cloud-error-reporting/pytest.ini @@ -21,3 +21,4 @@ filterwarnings = # Remove once opentelemetry stops triggering SelectableGroups DeprecationWarning on Python 3.11+ ignore:.*SelectableGroups dict interface is deprecated.*:DeprecationWarning ignore:(?s).*using a Python version.*past its end of life.*:FutureWarning + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning diff --git a/packages/google-cloud-firestore/noxfile.py b/packages/google-cloud-firestore/noxfile.py index b83aa0a5c973..899ba515509f 100644 --- a/packages/google-cloud-firestore/noxfile.py +++ b/packages/google-cloud-firestore/noxfile.py @@ -68,7 +68,7 @@ "asyncmock", "pytest", "pytest-cov", - "pytest-asyncio==0.21.2", + "pytest-asyncio", ] UNIT_TEST_EXTERNAL_DEPENDENCIES: List[str] = [ "aiounittest", @@ -86,7 +86,7 @@ "pytest", ] SYSTEM_TEST_EXTERNAL_DEPENDENCIES: List[str] = [ - "pytest-asyncio==0.21.2", + "pytest-asyncio", "six", "pyyaml", "pytest-xdist", diff --git a/packages/google-cloud-firestore/pytest.ini b/packages/google-cloud-firestore/pytest.ini index f895b60c3f63..ec7a5a783445 100644 --- a/packages/google-cloud-firestore/pytest.ini +++ b/packages/google-cloud-firestore/pytest.ini @@ -10,7 +10,7 @@ filterwarnings = # Remove once https://github.com/googleapis/python-firestore/issues/804 is fixed ignore:.*Detected filter using positional arguments:UserWarning # Remove once https://github.com/googleapis/python-firestore/pull/716 is merged - ignore:datetime.datetime.utcfromtimestamp\(\) is deprecated:DeprecationWarning + ignore:datetime.datetime.utcfromtimestamp\(\) is deprecated:DeprecationWarning ignore:datetime.datetime.utcnow\(\) is deprecated:DeprecationWarning # Remove warning once https://github.com/grpc/grpc/issues/35974 is fixed ignore:unclosed:ResourceWarning @@ -25,4 +25,4 @@ filterwarnings = ignore:(?s).*using a Python version.*past its end of life.*:FutureWarning # Remove once opentelemetry stops triggering SelectableGroups DeprecationWarning on Python 3.11+ ignore:.*SelectableGroups dict interface is deprecated.*:DeprecationWarning - + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning diff --git a/packages/google-cloud-firestore/tests/system/test_pipeline_acceptance.py b/packages/google-cloud-firestore/tests/system/test_pipeline_acceptance.py index 149182b13694..992554fe3916 100644 --- a/packages/google-cloud-firestore/tests/system/test_pipeline_acceptance.py +++ b/packages/google-cloud-firestore/tests/system/test_pipeline_acceptance.py @@ -208,7 +208,7 @@ def test_pipeline_results(test_dict, client): [t for t in yaml_loader() if "assert_error" in t], ids=id_format, ) -@pytest.mark.asyncio +@pytest.mark.asyncio(loop_scope="module") async def test_pipeline_expected_errors_async(test_dict, async_client): """ Finds assert_error statements in yaml, and ensures the pipeline raises the expected error @@ -234,7 +234,7 @@ async def test_pipeline_expected_errors_async(test_dict, async_client): ], ids=id_format, ) -@pytest.mark.asyncio +@pytest.mark.asyncio(loop_scope="module") async def test_pipeline_results_async(test_dict, async_client): """ Ensure pipeline returns expected results @@ -403,17 +403,6 @@ def _is_stage_string(yaml_str): ) -@pytest.fixture(scope="module") -def event_loop(): - """Change event_loop fixture to module level.""" - import asyncio - - policy = asyncio.get_event_loop_policy() - loop = policy.new_event_loop() - yield loop - loop.close() - - def _parse_yaml_types(data): """helper to convert yaml data to firestore objects when needed""" if isinstance(data, dict): diff --git a/packages/google-cloud-firestore/tests/system/test_system_async.py b/packages/google-cloud-firestore/tests/system/test_system_async.py index 27720fce3b23..dad70560a26d 100644 --- a/packages/google-cloud-firestore/tests/system/test_system_async.py +++ b/packages/google-cloud-firestore/tests/system/test_system_async.py @@ -84,7 +84,7 @@ ) -pytestmark = pytest.mark.asyncio +pytestmark = pytest.mark.asyncio(loop_scope="module") def _get_credentials_and_project(): @@ -166,7 +166,7 @@ def client(database): ) -@pytest_asyncio.fixture +@pytest_asyncio.fixture(loop_scope="module") async def cleanup(): operations = [] yield operations.append @@ -251,15 +251,6 @@ def _clean_results(results): return _verifier -@pytest.fixture(scope="module") -def event_loop(): - """Change event_loop fixture to module level.""" - policy = asyncio.get_event_loop_policy() - loop = policy.new_event_loop() - yield loop - loop.close() - - @pytest.mark.parametrize("database", TEST_DATABASES, indirect=True) async def test_collections(client, database): collections = [x async for x in client.collections(retry=RETRIES)] @@ -1256,7 +1247,7 @@ async def test_list_collections_with_read_time(client, cleanup, database): } -@pytest.mark.asyncio +@pytest.mark.asyncio(loop_scope="module") @pytest.mark.parametrize("database", [FIRESTORE_ENTERPRISE_DB], indirect=True) async def test_async_bson_document_read_and_write(client, cleanup, database): """Test async read and write operations for BSON types on Enterprise DB.""" @@ -1283,7 +1274,7 @@ async def test_async_bson_document_read_and_write(client, cleanup, database): assert snapshot.to_dict() == bson_payload -@pytest.mark.asyncio +@pytest.mark.asyncio(loop_scope="module") @pytest.mark.parametrize("database", [FIRESTORE_ENTERPRISE_DB], indirect=True) async def test_async_bson_regex_invalid_options(client, cleanup, database): """Test async write operations for BSONRegex with invalid options against backend.""" @@ -1298,7 +1289,7 @@ async def test_async_bson_regex_invalid_options(client, cleanup, database): assert "Invalid regex option" in exc_info.value.message -@pytest.mark.asyncio +@pytest.mark.asyncio(loop_scope="module") @pytest.mark.parametrize("database", [FIRESTORE_ENTERPRISE_DB], indirect=True) async def test_async_bson_decimal128_special_values(client, cleanup, database): """Test async write and read operations for BSONDecimal128 special values against backend.""" @@ -1325,7 +1316,7 @@ async def test_async_bson_decimal128_special_values(client, cleanup, database): } -@pytest_asyncio.fixture(scope="module") +@pytest_asyncio.fixture(scope="module", loop_scope="module") async def query_docs(client): collection_id = "qs" + UNIQUE_RESOURCE_ID sub_collection = "child" + UNIQUE_RESOURCE_ID @@ -1354,13 +1345,13 @@ async def query_docs(client): await operation() -@pytest_asyncio.fixture(scope="module") +@pytest_asyncio.fixture(scope="module", loop_scope="module") async def collection(query_docs): collection, _, _ = query_docs yield collection -@pytest_asyncio.fixture(scope="module") +@pytest_asyncio.fixture(scope="module", loop_scope="module") async def async_query(collection): return collection.where(filter=FieldFilter("a", "==", 1)) diff --git a/packages/google-cloud-firestore/tests/unit/v1/test_base_client.py b/packages/google-cloud-firestore/tests/unit/v1/test_base_client.py index 3762af7815eb..d2b2f15a6d2d 100644 --- a/packages/google-cloud-firestore/tests/unit/v1/test_base_client.py +++ b/packages/google-cloud-firestore/tests/unit/v1/test_base_client.py @@ -237,7 +237,8 @@ def test_baseclient__rpc_metadata_property_with_emulator(): ] -def test_baseclient__emulator_channel(): +@pytest.mark.asyncio +async def test_baseclient__emulator_channel(): from google.cloud.firestore_v1.services.firestore.transports.grpc import ( FirestoreGrpcTransport, ) diff --git a/packages/google-cloud-firestore/tests/unit/v1/test_bundle.py b/packages/google-cloud-firestore/tests/unit/v1/test_bundle.py index 3e8ea4e25b4b..8d864d7de591 100644 --- a/packages/google-cloud-firestore/tests/unit/v1/test_bundle.py +++ b/packages/google-cloud-firestore/tests/unit/v1/test_bundle.py @@ -345,27 +345,39 @@ def get_collection_class(cls): return async_collection.AsyncCollectionReference def test_async_query(self): - # Create an async query, but this test does not need to be - # marked as async by pytest because `bundle.add_named_query()` - # seemlessly handles accepting async iterables. + # `bundle.add_named_query()` is a synchronous method that internally + # calls `asyncio.get_event_loop().run_until_complete()` when given an + # `AsyncQuery`. Because `run_until_complete()` raises a RuntimeError if + # the loop is already running, this test cannot use + # `@pytest.mark.asyncio` (`async def`). Instead, we explicitly attach an + # idle event loop to the current thread because Python 3.14+ and + # `pytest-asyncio` do not implicitly provide one for sync tests. + import asyncio + from google.cloud.firestore_bundle import FirestoreBundle - async_query = self._bundled_query_helper() - bundle = FirestoreBundle("test") - bundle.add_named_query("asdf", async_query) - assert bundle.named_queries.get("asdf") is not None - assert ( - bundle.documents[ - f"projects/{DEFAULT_TEST_PROJECT}/databases/(default)/documents/col/doc-1" - ] - is not None - ) - assert ( - bundle.documents[ - f"projects/{DEFAULT_TEST_PROJECT}/databases/(default)/documents/col/doc-2" - ] - is not None - ) + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + try: + async_query = self._bundled_query_helper() + bundle = FirestoreBundle("test") + bundle.add_named_query("asdf", async_query) + assert bundle.named_queries.get("asdf") is not None + assert ( + bundle.documents[ + f"projects/{DEFAULT_TEST_PROJECT}/databases/(default)/documents/col/doc-1" + ] + is not None + ) + assert ( + bundle.documents[ + f"projects/{DEFAULT_TEST_PROJECT}/databases/(default)/documents/col/doc-2" + ] + is not None + ) + finally: + loop.close() + asyncio.set_event_loop(None) class TestBundleBuilder(_CollectionQueryMixin): diff --git a/packages/google-cloud-logging/pytest.ini b/packages/google-cloud-logging/pytest.ini index 942b21e9081b..7252713c4400 100644 --- a/packages/google-cloud-logging/pytest.ini +++ b/packages/google-cloud-logging/pytest.ini @@ -32,3 +32,4 @@ filterwarnings = ignore:(?s).*using a Python version.*past its end of life.*:FutureWarning # Remove once https://github.com/open-telemetry/opentelemetry-python/issues/5231 is fixed ignore:(?s).*SelectableGroups dict interface is deprecated. Use select.*:DeprecationWarning + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning diff --git a/packages/google-cloud-pubsub/pytest.ini b/packages/google-cloud-pubsub/pytest.ini index 571c4709ea25..843220465cfc 100644 --- a/packages/google-cloud-pubsub/pytest.ini +++ b/packages/google-cloud-pubsub/pytest.ini @@ -26,4 +26,4 @@ filterwarnings = ignore::FutureWarning:google.*: # Suppress SelectableGroups deprecation warning from older dependencies under Python 3.11+ ignore:.*SelectableGroups dict interface is deprecated:DeprecationWarning - + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning diff --git a/packages/google-cloud-runtimeconfig/pytest.ini b/packages/google-cloud-runtimeconfig/pytest.ini index 5b6dbd5ab09d..995191f5727f 100644 --- a/packages/google-cloud-runtimeconfig/pytest.ini +++ b/packages/google-cloud-runtimeconfig/pytest.ini @@ -10,3 +10,4 @@ filterwarnings = # This warning is expected for Python versions that approach EOL ignore:.*Please upgrade to the latest Python version.*:FutureWarning ignore:(?s).*using a Python version.*past its end of life.*:FutureWarning + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning diff --git a/packages/google-cloud-testutils/pytest.ini b/packages/google-cloud-testutils/pytest.ini index 3e849029ca53..530caa61543e 100644 --- a/packages/google-cloud-testutils/pytest.ini +++ b/packages/google-cloud-testutils/pytest.ini @@ -2,3 +2,4 @@ filterwarnings = # treat all warnings as errors error + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning diff --git a/packages/proto-plus/pytest.ini b/packages/proto-plus/pytest.ini index ba89114a1d71..2a2f40994b97 100644 --- a/packages/proto-plus/pytest.ini +++ b/packages/proto-plus/pytest.ini @@ -6,3 +6,4 @@ filterwarnings = ignore:.*custom tp_new.*in Python 3.14:DeprecationWarning # Remove once deprecated field `including_default_value_fields` is removed ignore:.*The argument `including_default_value_fields` has been removed.*:DeprecationWarning + ignore:.*asyncio_default_fixture_loop_scope.*:pytest.PytestDeprecationWarning