From 6e7b652d86f74ded569b1b91f058592fcbbfaf7d Mon Sep 17 00:00:00 2001 From: Julius Park Date: Tue, 5 Oct 2021 14:00:39 -0700 Subject: [PATCH] PYTHON-2914 MongoClient should raise an error when given multiple URIs (#747) --- doc/changelog.rst | 2 ++ doc/migrate-to-pymongo4.rst | 6 ++++++ pymongo/mongo_client.py | 16 +++++++++------- test/test_client.py | 5 +++++ 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/doc/changelog.rst b/doc/changelog.rst index b20314012..c4c4f35fe 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -157,6 +157,8 @@ Breaking Changes in 4.0 are passed to the server as-is rather than the previous behavior which substituted in a projection of ``{"_id": 1}``. This means that an empty projection will now return the entire document, not just the ``"_id"`` field. +- ``MongoClient()`` now raises a :exc:`~pymongo.errors.ConfigurationError` + when more than one URI is passed into the ``hosts`` argument. Notable improvements diff --git a/doc/migrate-to-pymongo4.rst b/doc/migrate-to-pymongo4.rst index eea17e8bc..7430ea50a 100644 --- a/doc/migrate-to-pymongo4.rst +++ b/doc/migrate-to-pymongo4.rst @@ -187,6 +187,12 @@ MongoClient cannot execute operations after ``close()`` after being closed. The previous behavior would simply reconnect. However, now you must create a new instance. +MongoClient raises exception when given more than one URI +......................................................... + +``MongoClient()`` now raises a :exc:`~pymongo.errors.ConfigurationError` +when more than one URI is passed into the ``hosts`` argument. + Database -------- diff --git a/pymongo/mongo_client.py b/pymongo/mongo_client.py index f105b1023..c0bcb9575 100644 --- a/pymongo/mongo_client.py +++ b/pymongo/mongo_client.py @@ -109,11 +109,9 @@ class MongoClient(common.BaseObject): The `host` parameter can be a full `mongodb URI `_, in addition to - a simple hostname. It can also be a list of hostnames or - URIs. Any port specified in the host string(s) will override - the `port` parameter. If multiple mongodb URIs containing - database or auth information are passed, the last database, - username, and password present will be used. For username and + a simple hostname. It can also be a list of hostnames but no more + than one URI. Any port specified in the host string(s) will override + the `port` parameter. For username and passwords reserved characters like ':', '/', '+' and '@' must be percent encoded following RFC 2396:: @@ -179,8 +177,9 @@ class MongoClient(common.BaseObject): :Parameters: - `host` (optional): hostname or IP address or Unix domain socket path of a single mongod or mongos instance to connect to, or a - mongodb URI, or a list of hostnames / mongodb URIs. If `host` is - an IPv6 literal it must be enclosed in '[' and ']' characters + mongodb URI, or a list of hostnames (but no more than one mongodb + URI). If `host` is an IPv6 literal it must be enclosed in '[' + and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost). Multihomed and round robin DNS addresses are **not** supported. - `port` (optional): port number on which to connect @@ -645,6 +644,9 @@ class MongoClient(common.BaseObject): dbase = None opts = common._CaseInsensitiveDictionary() fqdn = None + if len([h for h in host if "/" in h]) > 1: + raise ConfigurationError("host must not contain multiple MongoDB " + "URIs") for entity in host: # A hostname can only include a-z, 0-9, '-' and '.'. If we find a '/' # it must be a URI, diff --git a/test/test_client.py b/test/test_client.py index 993c58267..4398fa08b 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -466,6 +466,11 @@ class ClientUnitTest(unittest.TestCase): class TestClient(IntegrationTest): + def test_multiple_uris(self): + with self.assertRaises(ConfigurationError): + MongoClient(host=['mongodb+srv://cluster-a.abc12.mongodb.net', + 'mongodb+srv://cluster-b.abc12.mongodb.net', + 'mongodb+srv://cluster-c.abc12.mongodb.net']) def test_max_idle_time_reaper_default(self): with client_knobs(kill_cursor_frequency=0.1):