Repository: MongoEngine/mongoengine

Issue:
'readPreference' param in config URI was ignored in mongoengine.register_connection
I have a config string `'mongodb://mongodb01.test.vpc,mongodb02.test.vpc,mongodb03.test.vpc/prod?readPreference=secondaryPreferred'`

it was parsed to dict below by pymongo.uri_parser.parse_uri
```
{'collection': None,
 'database': 'prod',
 'nodelist': [('mongodb01.test.vpc', 27017),
  ('mongodb02.test.vpc', 27017),
  ('mongodb03.test.vpc', 27017)],
 'options': {'readpreference': 'secondaryPreferred'},
 'password': None,
 'username': None}
```
but mongoengine only read in 3 params if I read correctly, ignored 'readpreference'
```
            if 'replicaset' in uri_options:
                conn_settings['replicaSet'] = uri_options['replicaset']
            if 'authsource' in uri_options:
                conn_settings['authentication_source'] = uri_options['authsource']
            if 'authmechanism' in uri_options:
                conn_settings['authentication_mechanism'] = uri_options['authmechanism']
```
thus made my config not functioning as I needed.

 I don't know if this is a bug or a feature. To achieve my goal do I have to explicitly invoke `connect(..., read_preference=secondaryPreferred)`? Isn't controlling readpreference in a config string be more flexible?


Discussion:
duplicate of #1578 but this issue have more clear and concrete example.

<pre>
from mongoengine import * #pylint: disable=wildcard-import
from pymongo import ReadPreference
connect(host="mongodb://mongodb01.test.vpc,mongodb02.test.vpc,mongodb03.test.vpc/prod", read_preference=ReadPreference.SECONDARY_PREFFERED)
</pre>

Resolving patch:
diff --git a/mongoengine/connection.py b/mongoengine/connection.py
--- a/mongoengine/connection.py
+++ b/mongoengine/connection.py
@@ -103,6 +103,18 @@ def register_connection(alias, name=None, host=None, port=None,
                 conn_settings['authentication_source'] = uri_options['authsource']
             if 'authmechanism' in uri_options:
                 conn_settings['authentication_mechanism'] = uri_options['authmechanism']
+            if IS_PYMONGO_3 and 'readpreference' in uri_options:
+                read_preferences = (
+                    ReadPreference.NEAREST,
+                    ReadPreference.PRIMARY,
+                    ReadPreference.PRIMARY_PREFERRED,
+                    ReadPreference.SECONDARY,
+                    ReadPreference.SECONDARY_PREFERRED)
+                read_pf_mode = uri_options['readpreference'].lower()
+                for preference in read_preferences:
+                    if preference.name.lower() == read_pf_mode:
+                        conn_settings['read_preference'] = preference
+                        break
         else:
             resolved_hosts.append(entity)
     conn_settings['host'] = resolved_hosts


Test patch:
diff --git a/tests/test_connection.py b/tests/test_connection.py
--- a/tests/test_connection.py
+++ b/tests/test_connection.py
@@ -364,6 +364,12 @@ class DateDoc(Document):
         date_doc = DateDoc.objects.first()
         self.assertEqual(d, date_doc.the_date)
 
+    def test_read_preference_from_parse(self):
+        if IS_PYMONGO_3:
+            from pymongo import ReadPreference
+            conn = connect(host="mongodb://a1.vpc,a2.vpc,a3.vpc/prod?readPreference=secondaryPreferred")
+            self.assertEqual(conn.read_preference, ReadPreference.SECONDARY_PREFERRED)
+
     def test_multiple_connection_settings(self):
         connect('mongoenginetest', alias='t1', host="localhost")