Repository: MongoEngine/mongoengine

Issue:
read_preference_tags are not registered correct in the ReadPrecence Object
Hi All,

I'm trying to pass a read preference tags in my URI:

Using the following command:
mongo_connection = connect(host=config.MONGO_CONNECTION_URI)

With the following URI: 'mongodb://root:12345678@1.1.1.1:27017,2.2.2.2:27017,3.3.3.3:27017/api?replicaSet=s0&readPreference=secondary&readPreferenceTags=region:us-west-2,usage:api'


But the result I get when looking at the mongoclient created 

MongoClient(host=['1.1.1.1:27017', '2.2.2.2:27017', '3.3.3.3:27017'], document_class=dict, tz_aware=False, connect=True, replicaset='s0', readpreference='secondary', readpreferencetags=[{'region': 'us-west-2', 'usage': 'api'}], read_preference=Secondary(tag_sets=None, max_staleness=-1, hedge=None))

you can see tag_sets is empty and it's not taken into account, Please advise what is the best way to use read preference tags with MongoEngine


Discussion:

Resolving patch:
diff --git a/mongoengine/connection.py b/mongoengine/connection.py
--- a/mongoengine/connection.py
+++ b/mongoengine/connection.py
@@ -164,8 +164,16 @@ def _get_connection_settings(
                         preference.name.lower() == read_pf_mode
                         or preference.mode == read_pf_mode
                     ):
-                        conn_settings["read_preference"] = preference
+                        ReadPrefClass = preference.__class__
                         break
+
+                if "readpreferencetags" in uri_options:
+                    conn_settings["read_preference"] = ReadPrefClass(
+                        tag_sets=uri_options["readpreferencetags"]
+                    )
+                else:
+                    conn_settings["read_preference"] = ReadPrefClass()
+
             if "authmechanismproperties" in uri_options:
                 conn_settings["authmechanismproperties"] = uri_options[
                     "authmechanismproperties"


Test patch:
diff --git a/tests/test_connection.py b/tests/test_connection.py
--- a/tests/test_connection.py
+++ b/tests/test_connection.py
@@ -11,6 +11,7 @@
     InvalidOperation,
     OperationFailure,
 )
+from pymongo.read_preferences import Secondary
 
 import mongoengine.connection
 from mongoengine import (
@@ -24,6 +25,7 @@
 from mongoengine.connection import (
     DEFAULT_DATABASE_NAME,
     ConnectionFailure,
+    _get_connection_settings,
     disconnect,
     get_connection,
     get_db,
@@ -180,6 +182,35 @@ def test_connect_fails_if_similar_connection_settings_arent_defined_the_same_way
         with pytest.raises(ConnectionFailure):
             connect(host="mongodb://localhost:27017/%s" % db_name, alias=db_alias)
 
+    def test___get_connection_settings(self):
+        funky_host = "mongodb://root:12345678@1.1.1.1:27017,2.2.2.2:27017,3.3.3.3:27017/db_api?replicaSet=s0&readPreference=secondary&uuidRepresentation=javaLegacy&readPreferenceTags=region:us-west-2,usage:api"
+        settings = _get_connection_settings(host=funky_host)
+
+        if PYMONGO_VERSION < (4,):
+            read_pref = Secondary(
+                tag_sets=[{"region": "us-west-2", "usage": "api"}],
+                max_staleness=-1,
+            )
+        else:
+            read_pref = Secondary(
+                tag_sets=[{"region": "us-west-2", "usage": "api"}],
+                max_staleness=-1,
+                hedge=None,
+            )
+        assert settings == {
+            "authentication_mechanism": None,
+            "authentication_source": None,
+            "authmechanismproperties": None,
+            "host": [funky_host],
+            "name": "db_api",
+            "password": "12345678",
+            "port": 27017,
+            "read_preference": read_pref,
+            "replicaSet": "s0",
+            "username": "root",
+            "uuidrepresentation": "javaLegacy",
+        }
+
     def test_connect_passes_silently_connect_multiple_times_with_same_config(self):
         # test default connection to `test`
         connect()