diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 773c9ec0d8..cddcee0989 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -529,14 +529,6 @@ Python errors, such as missing imports, incorrect syntax, or other fatal typos. run `pre-commit run --all-files --hook-stage manual ruff` and fix all reported errors before running the `synchro` hook again. -## Converting a test to async - -The `tools/convert_test_to_async.py` script takes in an existing synchronous test file and outputs a -partially-converted asynchronous version of the same name to the `test/asynchronous` directory. -Use this generated file as a starting point for the completed conversion. - -The script is used like so: `python tools/convert_test_to_async.py [test_file.py]` - ## CPU profiling To profile a test script and generate a flame graph, follow these steps: diff --git a/tools/convert_test_to_async.py b/tools/convert_test_to_async.py deleted file mode 100644 index 9c8743d04c..0000000000 --- a/tools/convert_test_to_async.py +++ /dev/null @@ -1,141 +0,0 @@ -from __future__ import annotations - -import inspect -import sys - -from pymongo import AsyncMongoClient -from pymongo.asynchronous.collection import AsyncCollection -from pymongo.asynchronous.command_cursor import AsyncCommandCursor -from pymongo.asynchronous.cursor import AsyncCursor -from pymongo.asynchronous.database import AsyncDatabase - -replacements = { - "Collection": "AsyncCollection", - "Database": "AsyncDatabase", - "Cursor": "AsyncCursor", - "MongoClient": "AsyncMongoClient", - "CommandCursor": "AsyncCommandCursor", - "RawBatchCursor": "AsyncRawBatchCursor", - "RawBatchCommandCursor": "AsyncRawBatchCommandCursor", - "ClientSession": "AsyncClientSession", - "ChangeStream": "AsyncChangeStream", - "CollectionChangeStream": "AsyncCollectionChangeStream", - "DatabaseChangeStream": "AsyncDatabaseChangeStream", - "ClusterChangeStream": "AsyncClusterChangeStream", - "_Bulk": "_AsyncBulk", - "_ClientBulk": "_AsyncClientBulk", - "Connection": "AsyncConnection", - "synchronous": "asynchronous", - "Synchronous": "Asynchronous", - "next": "await anext", - "_Lock": "_ALock", - "_Condition": "_ACondition", - "GridFS": "AsyncGridFS", - "GridFSBucket": "AsyncGridFSBucket", - "GridIn": "AsyncGridIn", - "GridOut": "AsyncGridOut", - "GridOutCursor": "AsyncGridOutCursor", - "GridOutIterator": "AsyncGridOutIterator", - "GridOutChunkIterator": "_AsyncGridOutChunkIterator", - "_grid_in_property": "_a_grid_in_property", - "_grid_out_property": "_a_grid_out_property", - "ClientEncryption": "AsyncClientEncryption", - "MongoCryptCallback": "AsyncMongoCryptCallback", - "ExplicitEncrypter": "AsyncExplicitEncrypter", - "AutoEncrypter": "AsyncAutoEncrypter", - "ContextManager": "AsyncContextManager", - "ClientContext": "AsyncClientContext", - "TestCollection": "AsyncTestCollection", - "IntegrationTest": "AsyncIntegrationTest", - "PyMongoTestCase": "AsyncPyMongoTestCase", - "MockClientTest": "AsyncMockClientTest", - "client_context": "async_client_context", - "setUp": "asyncSetUp", - "tearDown": "asyncTearDown", - "wait_until": "await async_wait_until", - "addCleanup": "addAsyncCleanup", - "TestCase": "IsolatedAsyncioTestCase", - "UnitTest": "AsyncUnitTest", - "MockClient": "AsyncMockClient", - "SpecRunner": "AsyncSpecRunner", - "TransactionsBase": "AsyncTransactionsBase", - "get_pool": "await async_get_pool", - "is_mongos": "await async_is_mongos", - "rs_or_single_client": "await async_rs_or_single_client", - "rs_or_single_client_noauth": "await async_rs_or_single_client_noauth", - "rs_client": "await async_rs_client", - "single_client": "await async_single_client", - "from_client": "await async_from_client", - "closing": "aclosing", - "assertRaisesExactly": "asyncAssertRaisesExactly", - "get_mock_client": "await get_async_mock_client", - "close": "await aclose", -} - -async_classes = [AsyncMongoClient, AsyncDatabase, AsyncCollection, AsyncCursor, AsyncCommandCursor] - - -def get_async_methods() -> set[str]: - result: set[str] = set() - for x in async_classes: - methods = { - k - for k, v in vars(x).items() - if callable(v) - and not isinstance(v, classmethod) - and inspect.iscoroutinefunction(v) - and v.__name__[0] != "_" - } - result = result | methods - return result - - -async_methods = get_async_methods() - - -def apply_replacements(lines: list[str]) -> list[str]: - for i in range(len(lines)): - if "_IS_SYNC = True" in lines[i]: - lines[i] = "_IS_SYNC = False" - if "def test" in lines[i]: - lines[i] = lines[i].replace("def test", "async def test") - for k, value in replacements.items(): - if k in lines[i]: - lines[i] = lines[i].replace(k, value) - for k in async_methods: - if k + "(" in lines[i]: - tokens = lines[i].split(" ") - for j in range(len(tokens)): - if k + "(" in tokens[j]: - if j < 2: - tokens.insert(0, "await") - else: - tokens.insert(j, "await") - break - new_line = " ".join(tokens) - - lines[i] = new_line - - return lines - - -def process_file(input_file: str, output_file: str) -> None: - with open(input_file, "r+") as f: - lines = f.readlines() - lines = apply_replacements(lines) - - with open(output_file, "w+") as f2: - f2.seek(0) - f2.writelines(lines) - f2.truncate() - - -def main() -> None: - args = sys.argv[1:] - sync_file = "./test/" + args[0] - async_file = "./" + args[0] - - process_file(sync_file, async_file) - - -main() diff --git a/tools/synchro.py b/tools/synchro.py index 8132167e71..aa8cf0fe69 100644 --- a/tools/synchro.py +++ b/tools/synchro.py @@ -198,91 +198,6 @@ def async_only_test(f: Path) -> bool: if f.is_file() and not async_only_test(f) ] -# Add each asynchronized test here as part of the converting PR -converted_tests = [ - "__init__.py", - "conftest.py", - "helpers.py", - "pymongo_mocks.py", - "utils_spec_runner.py", - "qcheck.py", - "test_auth.py", - "test_auth_oidc.py", - "test_auth_spec.py", - "test_bulk.py", - "test_causal_consistency.py", - "test_change_stream.py", - "test_client.py", - "test_client_backpressure.py", - "test_client_bulk_write.py", - "test_client_context.py", - "test_client_metadata.py", - "test_collation.py", - "test_collection.py", - "test_collection_management.py", - "test_command_logging.py", - "test_command_logging.py", - "test_command_monitoring.py", - "test_comment.py", - "test_common.py", - "test_connection_logging.py", - "test_connection_monitoring.py", - "test_connections_survive_primary_stepdown_spec.py", - "test_create_entities.py", - "test_crud_unified.py", - "test_csot.py", - "test_cursor.py", - "test_custom_types.py", - "test_database.py", - "test_discovery_and_monitoring.py", - "test_dns.py", - "test_encryption.py", - "test_examples.py", - "test_grid_file.py", - "test_gridfs.py", - "test_gridfs_bucket.py", - "test_gridfs_spec.py", - "test_handshake_unified.py", - "test_heartbeat_monitoring.py", - "test_index_management.py", - "test_json_util_integration.py", - "test_load_balancer.py", - "test_logger.py", - "test_max_staleness.py", - "test_monitor.py", - "test_monitoring.py", - "test_mongos_load_balancing.py", - "test_on_demand_csfle.py", - "test_periodic_executor.py", - "test_pooling.py", - "test_raw_bson.py", - "test_read_concern.py", - "test_read_preferences.py", - "test_read_write_concern_spec.py", - "test_retryable_reads.py", - "test_retryable_reads_unified.py", - "test_retryable_writes.py", - "test_retryable_writes_unified.py", - "test_run_command.py", - "test_sdam_monitoring_spec.py", - "test_server_selection.py", - "test_server_selection_in_window.py", - "test_server_selection_logging.py", - "test_server_selection_rtt.py", - "test_session.py", - "test_sessions_unified.py", - "test_srv_polling.py", - "test_ssl.py", - "test_streaming_protocol.py", - "test_transactions.py", - "test_transactions_unified.py", - "test_unified_format.py", - "test_versioned_api_integration.py", - "unified_format.py", - "utils_selection_tests.py", - "utils.py", -] - def process_files( files: list[str], docstring_translate_files: list[str], sync_test_files: list[str] @@ -466,13 +381,12 @@ def main() -> None: unasync_directory(filtered_tests, _test_base, _test_dest_base, replacements) # Derive generated output paths directly from filtered source paths. - converted_tests_set = set(converted_tests) generated_pymongo = [_pymongo_dest_base + Path(f).name for f in filtered_async] generated_gridfs = [_gridfs_dest_base + Path(f).name for f in filtered_gridfs] generated_tests = [ _test_dest_base + Path(f).name for f in filtered_tests - if Path(f).name in converted_tests_set and (Path(_test_dest_base) / Path(f).name).is_file() + if (Path(_test_dest_base) / Path(f).name).is_file() ] docstring_translate_files = generated_pymongo + generated_gridfs + generated_tests