Repository: celery/kombu

Issue:
unexpected keyword argument 'query' when using pymongo 3.0
```
  File "/opt/ampli/apps/marvintaskmgr/venv/lib/python2.7/site-packages/kombu/transport/virtual/__init__.py", line 487, in queue_bind
    self._queue_bind(exchange, *meta)
  File "/opt/ampli/apps/marvintaskmgr/venv/lib/python2.7/site-packages/kombu/transport/mongodb.py", line 244, in _queue_bind
    self.create_broadcast_cursor(exchange, routing_key, pattern, queue)
  File "/opt/ampli/apps/marvintaskmgr/venv/lib/python2.7/site-packages/kombu/transport/mongodb.py", line 302, in create_broadcast_cursor
    tailable=True,
  File "/opt/ampli/apps/marvintaskmgr/venv/lib/python2.7/site-packages/pymongo/collection.py", line 929, in find
    return Cursor(self, *args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'query'
```

https://github.com/celery/kombu/blob/8e6aed9fcf978b6c34108c0d37b720bd125f0352/kombu/transport/mongodb.py#L297-L300

query and tailable are invalid arguments with pymongo 3.0



Discussion:

Resolving patch:
diff --git a/kombu/transport/mongodb.py b/kombu/transport/mongodb.py
--- a/kombu/transport/mongodb.py
+++ b/kombu/transport/mongodb.py
@@ -14,6 +14,7 @@
 
 from pymongo import errors
 from pymongo import MongoClient, uri_parser
+from pymongo.cursor import CursorType
 
 from kombu.five import Empty
 from kombu.syn import _detect_environment
@@ -179,17 +180,23 @@ def _parse_uri(self, scheme='mongodb://'):
     def _prepare_client_options(self, options):
         if pymongo.version_tuple >= (3, ):
             options.pop('auto_start_request', None)
+        return options
 
     def _open(self, scheme='mongodb://'):
         hostname, dbname, options = self._parse_uri(scheme=scheme)
 
-        self._prepare_client_options(options)
-        mongoconn = MongoClient(
-            host=hostname, ssl=options['ssl'],
-            auto_start_request=options['auto_start_request'],
-            connectTimeoutMS=options['connectTimeoutMS'],
-            use_greenlets=_detect_environment() != 'default',
-        )
+        conf = self._prepare_client_options(options)
+        conf['host'] = hostname
+
+        env = _detect_environment()
+        if env == 'gevent':
+            from gevent import monkey
+            monkey.patch_all()
+        elif env == 'eventlet':
+            from eventlet import monkey_patch
+            monkey_patch()
+
+        mongoconn = MongoClient(**conf)
         database = mongoconn[dbname]
 
         version = mongoconn.server_info()['version']
@@ -294,11 +301,18 @@ def get_broadcast_cursor(self, queue):
             )
 
     def create_broadcast_cursor(self, exchange, routing_key, pattern, queue):
-        cursor = self.get_broadcast().find(
-            query={'queue': exchange},
-            sort=[('$natural', 1)],
-            tailable=True,
-        )
+        if pymongo.version_tuple >= (3, ):
+            query = dict(filter={'queue': exchange},
+                         sort=[('$natural', 1)],
+                         cursor_type=CursorType.TAILABLE
+                         )
+        else:
+            query = dict(query={'queue': exchange},
+                         sort=[('$natural', 1)],
+                         tailable=True
+                         )
+
+        cursor = self.get_broadcast().find(**query)
         ret = self._broadcast_cursors[queue] = BroadcastCursor(cursor)
         return ret
 


Test patch: