Skip to content

Commit 3ed3c7f

Browse files
authored
Merge pull request pandas-dev#552 from srf94/pymongo_kwargs
Added kwargs to Arctic init for extra MongoClient parameters (Issue 493)
2 parents 0115882 + 64cbf4c commit 3ed3c7f

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### 1.70
44
* Bugfix: #629 - Column kwarg no longer modified
55
* Bugfix: #641 - DateRange.intersection open/closed range fix
6+
* Feature: #493 Can pass kwargs when calling MongoClient, e.g. for ssl
67

78
### 1.69 (2018-09-12)
89
* Docs: VersionStore documentation

arctic/arctic.py

+17-5
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,13 @@ class Arctic(object):
7070

7171
def __init__(self, mongo_host, app_name=APPLICATION_NAME, allow_secondary=False,
7272
socketTimeoutMS=10 * 60 * 1000, connectTimeoutMS=2 * 1000,
73-
serverSelectionTimeoutMS=30 * 1000):
73+
serverSelectionTimeoutMS=30 * 1000, **kwargs):
7474
"""
7575
Constructs a Arctic Datastore.
7676
77+
Note: If mongo_host is a pymongo connection and the process is later forked, the
78+
new pymongo connection may have different parameters.
79+
7780
Parameters:
7881
-----------
7982
mongo_host: A MongoDB hostname, alias or Mongo Connection
@@ -92,6 +95,8 @@ def __init__(self, mongo_host, app_name=APPLICATION_NAME, allow_secondary=False,
9295
the pymongo driver will spend on MongoDB cluster discovery. This parameter
9396
takes precedence over connectTimeoutMS: https://jira.mongodb.org/browse/DRIVERS-222
9497
98+
kwargs: 'dict' extra keyword arguments to pass when calling pymongo.MongoClient,
99+
for example ssl parameters.
95100
"""
96101
self._application_name = app_name
97102
self._library_cache = {}
@@ -101,10 +106,13 @@ def __init__(self, mongo_host, app_name=APPLICATION_NAME, allow_secondary=False,
101106
self._server_selection_timeout = serverSelectionTimeoutMS
102107
self._lock = threading.RLock()
103108
self._pid = os.getpid()
109+
self._pymongo_kwargs = kwargs
104110

105111
if isinstance(mongo_host, string_types):
112+
self._given_instance = False
106113
self.mongo_host = mongo_host
107114
else:
115+
self._given_instance = True
108116
self.__conn = mongo_host
109117
# Workaround for: https://jira.mongodb.org/browse/PYTHON-927
110118
mongo_host.server_info()
@@ -119,17 +127,21 @@ def _conn(self):
119127
# http://api.mongodb.com/python/current/faq.html#using-pymongo-with-multiprocessing
120128
curr_pid = os.getpid()
121129
if curr_pid != self._pid:
130+
if self._given_instance:
131+
logger.warn("Forking process. Arctic was passed a pymongo connection during init, "
132+
"the new pymongo connection may have different parameters.")
122133
self._pid = curr_pid # this line has to precede reset() otherwise we get to eternal recursion
123134
self.reset() # also triggers re-auth
124135

125136
if self.__conn is None:
126137
host = get_mongodb_uri(self.mongo_host)
127138
logger.info("Connecting to mongo: {0} ({1})".format(self.mongo_host, host))
128139
self.__conn = pymongo.MongoClient(host=host,
129-
maxPoolSize=self._MAX_CONNS,
130-
socketTimeoutMS=self._socket_timeout,
131-
connectTimeoutMS=self._connect_timeout,
132-
serverSelectionTimeoutMS=self._server_selection_timeout)
140+
maxPoolSize=self._MAX_CONNS,
141+
socketTimeoutMS=self._socket_timeout,
142+
connectTimeoutMS=self._connect_timeout,
143+
serverSelectionTimeoutMS=self._server_selection_timeout,
144+
**self._pymongo_kwargs)
133145
self._adminDB = self.__conn.admin
134146

135147
# Authenticate against admin for the user

tests/unit/test_arctic.py

+32
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,38 @@ def test_arctic_lazy_init():
2626
assert mc.called
2727

2828

29+
def test_arctic_lazy_init_ssl_true():
30+
with patch('pymongo.MongoClient', return_value=MagicMock(), autospec=True) as mc, \
31+
patch('arctic.arctic.mongo_retry', side_effect=lambda x: x, autospec=True), \
32+
patch('arctic.arctic.get_auth', autospec=True) as ga:
33+
store = Arctic('cluster', ssl=True)
34+
assert not mc.called
35+
# do something to trigger lazy arctic init
36+
store.list_libraries()
37+
assert mc.called
38+
assert len(mc.mock_calls) == 1
39+
assert mc.mock_calls[0] == call(connectTimeoutMS=2000,
40+
host='cluster',
41+
maxPoolSize=4,
42+
serverSelectionTimeoutMS=30000,
43+
socketTimeoutMS=600000,
44+
ssl=True)
45+
46+
47+
def test_connection_passed_warning_raised():
48+
with patch('pymongo.MongoClient', return_value=MagicMock(), autospec=True), \
49+
patch('arctic.arctic.mongo_retry', side_effect=lambda x: x, autospec=True), \
50+
patch('arctic.arctic.get_auth', autospec=True), \
51+
patch('arctic.arctic.logger') as lg:
52+
magic_mock = MagicMock(nodes={("host", "port")})
53+
store = Arctic(magic_mock, ssl=True)
54+
# Increment _pid to simulate forking the process
55+
store._pid += 1
56+
_ = store._conn
57+
assert lg.mock_calls[0] == call.warn('Forking process. Arctic was passed a pymongo connection during init, '
58+
'the new pymongo connection may have different parameters.')
59+
60+
2961
def test_arctic_auth():
3062
with patch('pymongo.MongoClient', return_value=MagicMock(), autospec=True), \
3163
patch('arctic.arctic.mongo_retry', autospec=True), \

0 commit comments

Comments
 (0)