diff --git a/pymongo/asynchronous/mongo_client.py b/pymongo/asynchronous/mongo_client.py index 8ca7bca436..71478d558c 100644 --- a/pymongo/asynchronous/mongo_client.py +++ b/pymongo/asynchronous/mongo_client.py @@ -1043,6 +1043,7 @@ async def target() -> bool: def append_metadata(self, driver_info: DriverInfo) -> None: """Appends the given metadata to existing driver metadata. + If given driver_info.name is already present in the metadata, no append is done. :param driver_info: a :class:`~pymongo.driver_info.DriverInfo` @@ -1053,7 +1054,11 @@ def append_metadata(self, driver_info: DriverInfo) -> None: raise TypeError( f"driver_info must be an instance of DriverInfo, not {type(driver_info)}" ) - self._options.pool_options._update_metadata(driver_info) + if ( + driver_info.name + and driver_info.name not in self._options.pool_options.metadata["driver"]["name"] + ): + self._options.pool_options._update_metadata(driver_info) def _should_pin_cursor(self, session: Optional[AsyncClientSession]) -> Optional[bool]: return self._options.load_balanced and not (session and session.in_transaction) diff --git a/pymongo/synchronous/mongo_client.py b/pymongo/synchronous/mongo_client.py index f44368ec5c..629c9939a4 100644 --- a/pymongo/synchronous/mongo_client.py +++ b/pymongo/synchronous/mongo_client.py @@ -1043,6 +1043,7 @@ def target() -> bool: def append_metadata(self, driver_info: DriverInfo) -> None: """Appends the given metadata to existing driver metadata. + If given driver_info.name is already present in the metadata, no append is done. :param driver_info: a :class:`~pymongo.driver_info.DriverInfo` @@ -1053,7 +1054,11 @@ def append_metadata(self, driver_info: DriverInfo) -> None: raise TypeError( f"driver_info must be an instance of DriverInfo, not {type(driver_info)}" ) - self._options.pool_options._update_metadata(driver_info) + if ( + driver_info.name + and driver_info.name not in self._options.pool_options.metadata["driver"]["name"] + ): + self._options.pool_options._update_metadata(driver_info) def _should_pin_cursor(self, session: Optional[ClientSession]) -> Optional[bool]: return self._options.load_balanced and not (session and session.in_transaction) diff --git a/test/asynchronous/test_client_metadata.py b/test/asynchronous/test_client_metadata.py index cfecb49748..935a982e74 100644 --- a/test/asynchronous/test_client_metadata.py +++ b/test/asynchronous/test_client_metadata.py @@ -96,6 +96,7 @@ async def check_metadata_added( add_name: str, add_version: Optional[str], add_platform: Optional[str], + is_duplicate: bool = False, ) -> None: # send initial metadata name, version, platform, metadata = await self.send_ping_and_get_metadata(client, True) @@ -107,15 +108,22 @@ async def check_metadata_added( new_name, new_version, new_platform, new_metadata = await self.send_ping_and_get_metadata( client, True ) - self.assertEqual(new_name, f"{name}|{add_name}" if add_name is not None else name) - self.assertEqual( - new_version, - f"{version}|{add_version}" if add_version is not None else version, - ) - self.assertEqual( - new_platform, - f"{platform}|{add_platform}" if add_platform is not None else platform, - ) + + if not is_duplicate: + self.assertEqual(new_name, f"{name}|{add_name}" if add_name is not None else name) + self.assertEqual( + new_version, + f"{version}|{add_version}" if add_version is not None else version, + ) + self.assertEqual( + new_platform, + f"{platform}|{add_platform}" if add_platform is not None else platform, + ) + # Metadata should be unchanged if the new name was already present + else: + self.assertEqual(new_name, name) + self.assertEqual(new_version, version) + self.assertEqual(new_platform, platform) metadata.pop("driver") metadata.pop("platform") @@ -210,6 +218,16 @@ async def test_doesnt_update_established_connections(self): self.assertIsNone(self.handshake_req) self.assertEqual(listener.event_count(ConnectionClosedEvent), 0) + async def test_append_metadata_duplicate_name(self): + client = await self.async_rs_or_single_client( + "mongodb://" + self.server.address_string, + maxIdleTimeMS=1, + driver=DriverInfo("library", "1.2", "Library Platform"), + ) + await self.check_metadata_added( + client, "library", "2.0", "Framework Platform", is_duplicate=True + ) + if __name__ == "__main__": unittest.main() diff --git a/test/test_client_metadata.py b/test/test_client_metadata.py index 32cb9b8009..440981d1af 100644 --- a/test/test_client_metadata.py +++ b/test/test_client_metadata.py @@ -96,6 +96,7 @@ def check_metadata_added( add_name: str, add_version: Optional[str], add_platform: Optional[str], + is_duplicate: bool = False, ) -> None: # send initial metadata name, version, platform, metadata = self.send_ping_and_get_metadata(client, True) @@ -107,15 +108,22 @@ def check_metadata_added( new_name, new_version, new_platform, new_metadata = self.send_ping_and_get_metadata( client, True ) - self.assertEqual(new_name, f"{name}|{add_name}" if add_name is not None else name) - self.assertEqual( - new_version, - f"{version}|{add_version}" if add_version is not None else version, - ) - self.assertEqual( - new_platform, - f"{platform}|{add_platform}" if add_platform is not None else platform, - ) + + if not is_duplicate: + self.assertEqual(new_name, f"{name}|{add_name}" if add_name is not None else name) + self.assertEqual( + new_version, + f"{version}|{add_version}" if add_version is not None else version, + ) + self.assertEqual( + new_platform, + f"{platform}|{add_platform}" if add_platform is not None else platform, + ) + # Metadata should be unchanged if the new name was already present + else: + self.assertEqual(new_name, name) + self.assertEqual(new_version, version) + self.assertEqual(new_platform, platform) metadata.pop("driver") metadata.pop("platform") @@ -210,6 +218,14 @@ def test_doesnt_update_established_connections(self): self.assertIsNone(self.handshake_req) self.assertEqual(listener.event_count(ConnectionClosedEvent), 0) + def test_append_metadata_duplicate_name(self): + client = self.rs_or_single_client( + "mongodb://" + self.server.address_string, + maxIdleTimeMS=1, + driver=DriverInfo("library", "1.2", "Library Platform"), + ) + self.check_metadata_added(client, "library", "2.0", "Framework Platform", is_duplicate=True) + if __name__ == "__main__": unittest.main()