PYTHON-2164 Add MongoClient.options, remove redundant properties (#772)
This commit is contained in:
parent
9f6c6a3061
commit
b342990934
7
doc/api/pymongo/client_options.rst
Normal file
7
doc/api/pymongo/client_options.rst
Normal file
@ -0,0 +1,7 @@
|
||||
:mod:`client_options` -- Read only configuration options for a MongoClient.
|
||||
===========================================================================
|
||||
|
||||
.. automodule:: pymongo.client_options
|
||||
|
||||
.. autoclass:: pymongo.client_options.ClientOptions()
|
||||
:members:
|
||||
@ -29,6 +29,7 @@ Sub-modules:
|
||||
|
||||
bulk
|
||||
change_stream
|
||||
client_options
|
||||
client_session
|
||||
collation
|
||||
collection
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
|
||||
Raises :class:`~pymongo.errors.InvalidName` if an invalid database name is used.
|
||||
|
||||
.. autoattribute:: event_listeners
|
||||
.. autoattribute:: topology_description
|
||||
.. autoattribute:: address
|
||||
.. autoattribute:: primary
|
||||
@ -22,16 +21,12 @@
|
||||
.. autoattribute:: arbiters
|
||||
.. autoattribute:: is_primary
|
||||
.. autoattribute:: is_mongos
|
||||
.. autoattribute:: max_pool_size
|
||||
.. autoattribute:: min_pool_size
|
||||
.. autoattribute:: max_idle_time_ms
|
||||
.. autoattribute:: nodes
|
||||
.. autoattribute:: local_threshold_ms
|
||||
.. autoattribute:: server_selection_timeout
|
||||
.. autoattribute:: codec_options
|
||||
.. autoattribute:: read_preference
|
||||
.. autoattribute:: write_concern
|
||||
.. autoattribute:: read_concern
|
||||
.. autoattribute:: options
|
||||
.. automethod:: start_session
|
||||
.. automethod:: list_databases
|
||||
.. automethod:: list_database_names
|
||||
|
||||
@ -2,5 +2,6 @@
|
||||
==============================================================
|
||||
|
||||
.. automodule:: pymongo.pool
|
||||
:synopsis: Pool module for use with a MongoDB client.
|
||||
:members:
|
||||
|
||||
.. autoclass:: pymongo.pool.PoolOptions()
|
||||
:members:
|
||||
|
||||
@ -36,6 +36,13 @@ Breaking Changes in 4.0
|
||||
- Removed :attr:`pymongo.mongo_client.MongoClient.max_bson_size`.
|
||||
- Removed :attr:`pymongo.mongo_client.MongoClient.max_message_size`.
|
||||
- Removed :attr:`pymongo.mongo_client.MongoClient.max_write_batch_size`.
|
||||
- Removed :attr:`pymongo.mongo_client.MongoClient.event_listeners`.
|
||||
- Removed :attr:`pymongo.mongo_client.MongoClient.max_pool_size`.
|
||||
- Removed :attr:`pymongo.mongo_client.MongoClient.max_idle_time_ms`.
|
||||
- Removed :attr:`pymongo.mongo_client.MongoClient.local_threshold_ms`.
|
||||
- Removed :attr:`pymongo.mongo_client.MongoClient.server_selection_timeout`.
|
||||
- Removed :attr:`pymongo.mongo_client.MongoClient.retry_writes`.
|
||||
- Removed :attr:`pymongo.mongo_client.MongoClient.retry_reads`.
|
||||
- Removed :meth:`pymongo.database.Database.eval`,
|
||||
:data:`pymongo.database.Database.system_js` and
|
||||
:class:`pymongo.database.SystemJS`.
|
||||
@ -180,6 +187,8 @@ Notable improvements
|
||||
will connect to. More specifically, when a mongodb+srv:// connection string
|
||||
resolves to more than `srvMaxHosts` number of hosts, the client will randomly
|
||||
choose a `srvMaxHosts` sized subset of hosts.
|
||||
- Added :attr:`pymongo.mongo_client.MongoClient.options` for read-only access
|
||||
to a client's configuration options.
|
||||
|
||||
Issues Resolved
|
||||
...............
|
||||
@ -2121,7 +2130,7 @@ Important new features:
|
||||
- The ``max_pool_size`` option for :class:`~pymongo.mongo_client.MongoClient`
|
||||
and :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient` now
|
||||
actually caps the number of sockets the pool will open concurrently.
|
||||
Once the pool has reached :attr:`~pymongo.mongo_client.MongoClient.max_pool_size`
|
||||
Once the pool has reaches max_pool_size
|
||||
operations will block waiting for a socket to become available. If
|
||||
``waitQueueTimeoutMS`` is set, an operation that blocks waiting for a socket
|
||||
will raise :exc:`~pymongo.errors.ConnectionFailure` after the timeout. By
|
||||
|
||||
@ -196,6 +196,37 @@ can be changed to this::
|
||||
|
||||
.. _hello command: https://docs.mongodb.com/manual/reference/command/hello/
|
||||
|
||||
MongoClient.event_listeners and other configuration option helpers are removed
|
||||
..............................................................................
|
||||
|
||||
The following client configuration option helpers are removed:
|
||||
- :attr:`pymongo.mongo_client.MongoClient.event_listeners`.
|
||||
- :attr:`pymongo.mongo_client.MongoClient.max_pool_size`.
|
||||
- :attr:`pymongo.mongo_client.MongoClient.max_idle_time_ms`.
|
||||
- :attr:`pymongo.mongo_client.MongoClient.local_threshold_ms`.
|
||||
- :attr:`pymongo.mongo_client.MongoClient.server_selection_timeout`.
|
||||
- :attr:`pymongo.mongo_client.MongoClient.retry_writes`.
|
||||
- :attr:`pymongo.mongo_client.MongoClient.retry_reads`.
|
||||
|
||||
These helpers have been replaced by
|
||||
:attr:`pymongo.mongo_client.MongoClient.options`. Code like this::
|
||||
|
||||
client.event_listeners
|
||||
client.local_threshold_ms
|
||||
client.server_selection_timeout
|
||||
client.max_pool_size
|
||||
client.min_pool_size
|
||||
client.max_idle_time_ms
|
||||
|
||||
can be changed to this::
|
||||
|
||||
client.options.event_listeners
|
||||
client.options.local_threshold_ms
|
||||
client.options.server_selection_timeout
|
||||
client.options.pool_options.max_pool_size
|
||||
client.options.pool_options.min_pool_size
|
||||
client.options.pool_options.max_idle_time_seconds
|
||||
|
||||
``tz_aware`` defaults to ``False``
|
||||
..................................
|
||||
|
||||
|
||||
@ -153,8 +153,12 @@ def _parse_pool_options(options):
|
||||
|
||||
|
||||
class ClientOptions(object):
|
||||
"""Read only configuration options for a MongoClient.
|
||||
|
||||
"""ClientOptions"""
|
||||
Should not be instantiated directly by application developers. Access
|
||||
a client's options via :attr:`pymongo.mongo_client.MongoClient.options`
|
||||
instead.
|
||||
"""
|
||||
|
||||
def __init__(self, username, password, database, options):
|
||||
self.__options = options
|
||||
@ -200,7 +204,7 @@ class ClientOptions(object):
|
||||
return self.__codec_options
|
||||
|
||||
@property
|
||||
def credentials(self):
|
||||
def _credentials(self):
|
||||
"""A :class:`~pymongo.auth.MongoCredentials` instance or None."""
|
||||
return self.__credentials
|
||||
|
||||
@ -272,3 +276,13 @@ class ClientOptions(object):
|
||||
def load_balanced(self):
|
||||
"""True if the client was configured to connect to a load balancer."""
|
||||
return self.__load_balanced
|
||||
|
||||
@property
|
||||
def event_listeners(self):
|
||||
"""The event listeners registered for this client.
|
||||
|
||||
See :mod:`~pymongo.monitoring` for details.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
"""
|
||||
return self.__pool_options._event_listeners.event_listeners()
|
||||
|
||||
@ -261,7 +261,7 @@ class _Encrypter(object):
|
||||
self._internal_client = None
|
||||
|
||||
def _get_internal_client(encrypter, mongo_client):
|
||||
if mongo_client.max_pool_size is None:
|
||||
if mongo_client.options.pool_options.max_pool_size is None:
|
||||
# Unlimited pool size, use the same client.
|
||||
return mongo_client
|
||||
# Else - limited pool size, use an internal client.
|
||||
|
||||
@ -722,14 +722,14 @@ class MongoClient(common.BaseObject):
|
||||
self.__lock = threading.Lock()
|
||||
self.__kill_cursors_queue = []
|
||||
|
||||
self._event_listeners = options.pool_options.event_listeners
|
||||
self._event_listeners = options.pool_options._event_listeners
|
||||
super(MongoClient, self).__init__(options.codec_options,
|
||||
options.read_preference,
|
||||
options.write_concern,
|
||||
options.read_concern)
|
||||
|
||||
self.__all_credentials = {}
|
||||
creds = options.credentials
|
||||
creds = options._credentials
|
||||
if creds:
|
||||
self.__all_credentials[creds.source] = creds
|
||||
|
||||
@ -893,14 +893,6 @@ class MongoClient(common.BaseObject):
|
||||
batch_size, collation, start_at_operation_time, session,
|
||||
start_after)
|
||||
|
||||
@property
|
||||
def event_listeners(self):
|
||||
"""The event listeners registered for this client.
|
||||
|
||||
See :mod:`~pymongo.monitoring` for details.
|
||||
"""
|
||||
return self._event_listeners.event_listeners()
|
||||
|
||||
@property
|
||||
def topology_description(self):
|
||||
"""The description of the connected MongoDB deployment.
|
||||
@ -1005,40 +997,6 @@ class MongoClient(common.BaseObject):
|
||||
"""
|
||||
return self._server_property('server_type') == SERVER_TYPE.Mongos
|
||||
|
||||
@property
|
||||
def max_pool_size(self):
|
||||
"""The maximum allowable number of concurrent connections to each
|
||||
connected server. Requests to a server will block if there are
|
||||
`maxPoolSize` outstanding connections to the requested server.
|
||||
Defaults to 100. Can be either 0 or None, in which case there is no
|
||||
limit on the number of concurrent connections.
|
||||
|
||||
When a server's pool has reached `max_pool_size`, operations for that
|
||||
server block waiting for a socket to be returned to the pool. If
|
||||
``waitQueueTimeoutMS`` is set, a blocked operation will raise
|
||||
:exc:`~pymongo.errors.ConnectionFailure` after a timeout.
|
||||
By default ``waitQueueTimeoutMS`` is not set.
|
||||
"""
|
||||
return self.__options.pool_options.max_pool_size
|
||||
|
||||
@property
|
||||
def min_pool_size(self):
|
||||
"""The minimum required number of concurrent connections that the pool
|
||||
will maintain to each connected server. Default is 0.
|
||||
"""
|
||||
return self.__options.pool_options.min_pool_size
|
||||
|
||||
@property
|
||||
def max_idle_time_ms(self):
|
||||
"""The maximum number of milliseconds that a connection can remain
|
||||
idle in the pool before being removed and replaced. Defaults to
|
||||
`None` (no limit).
|
||||
"""
|
||||
seconds = self.__options.pool_options.max_idle_time_seconds
|
||||
if seconds is None:
|
||||
return None
|
||||
return 1000 * seconds
|
||||
|
||||
@property
|
||||
def nodes(self):
|
||||
"""Set of all currently connected servers.
|
||||
@ -1054,38 +1012,15 @@ class MongoClient(common.BaseObject):
|
||||
return frozenset(s.address for s in description.known_servers)
|
||||
|
||||
@property
|
||||
def local_threshold_ms(self):
|
||||
"""The local threshold for this instance."""
|
||||
return self.__options.local_threshold_ms
|
||||
def options(self):
|
||||
"""The configuration options for this client.
|
||||
|
||||
@property
|
||||
def server_selection_timeout(self):
|
||||
"""The server selection timeout for this instance in seconds."""
|
||||
return self.__options.server_selection_timeout
|
||||
:Returns:
|
||||
An instance of :class:`~pymongo.client_options.ClientOptions`.
|
||||
|
||||
@property
|
||||
def retry_writes(self):
|
||||
"""If this instance should retry supported write operations."""
|
||||
return self.__options.retry_writes
|
||||
|
||||
@property
|
||||
def retry_reads(self):
|
||||
"""If this instance should retry supported write operations."""
|
||||
return self.__options.retry_reads
|
||||
|
||||
def _is_writable(self):
|
||||
"""Attempt to connect to a writable server, or return False.
|
||||
.. versionadded:: 4.0
|
||||
"""
|
||||
topology = self._get_topology() # Starts monitors if necessary.
|
||||
try:
|
||||
svr = topology.select_server(writable_server_selector)
|
||||
|
||||
# When directly connected to a secondary, arbiter, etc.,
|
||||
# select_server returns it, whatever the selector. Check
|
||||
# again if the server is writable.
|
||||
return svr.description.is_writable
|
||||
except ConnectionFailure:
|
||||
return False
|
||||
return self.__options
|
||||
|
||||
def _end_sessions(self, session_ids):
|
||||
"""Send endSessions command(s) with the given session ids."""
|
||||
@ -1282,7 +1217,7 @@ class MongoClient(common.BaseObject):
|
||||
|
||||
Re-raises any exception thrown by func().
|
||||
"""
|
||||
retryable = (retryable and self.retry_writes
|
||||
retryable = (retryable and self.options.retry_writes
|
||||
and session and not session.in_transaction)
|
||||
return self._retry_internal(retryable, func, session, bulk)
|
||||
|
||||
@ -1353,7 +1288,7 @@ class MongoClient(common.BaseObject):
|
||||
Re-raises any exception thrown by func().
|
||||
"""
|
||||
retryable = (retryable and
|
||||
self.retry_reads
|
||||
self.options.retry_reads
|
||||
and not (session and session.in_transaction))
|
||||
last_error = None
|
||||
retrying = False
|
||||
|
||||
@ -123,7 +123,7 @@ class Monitor(MonitorBase):
|
||||
self._server_description = server_description
|
||||
self._pool = pool
|
||||
self._settings = topology_settings
|
||||
self._listeners = self._settings._pool_options.event_listeners
|
||||
self._listeners = self._settings._pool_options._event_listeners
|
||||
pub = self._listeners is not None
|
||||
self._publish = pub and self._listeners.enabled_for_server_heartbeat
|
||||
self._cancel_context = None
|
||||
|
||||
@ -1318,10 +1318,10 @@ class _EventListeners(object):
|
||||
|
||||
def event_listeners(self):
|
||||
"""List of registered event listeners."""
|
||||
return (self.__command_listeners[:] +
|
||||
self.__server_heartbeat_listeners[:] +
|
||||
self.__server_listeners[:] +
|
||||
self.__topology_listeners[:] +
|
||||
return (self.__command_listeners +
|
||||
self.__server_heartbeat_listeners +
|
||||
self.__server_listeners +
|
||||
self.__topology_listeners +
|
||||
self.__cmap_listeners)
|
||||
|
||||
def publish_command_start(self, command, database_name,
|
||||
|
||||
@ -256,6 +256,17 @@ def _cond_wait(condition, deadline):
|
||||
|
||||
|
||||
class PoolOptions(object):
|
||||
"""Read only connection pool options for a MongoClient.
|
||||
|
||||
Should not be instantiated directly by application developers. Access
|
||||
a client's pool options via
|
||||
:attr:`~pymongo.client_options.ClientOptions.pool_options` instead::
|
||||
|
||||
pool_opts = client.options.pool_options
|
||||
pool_opts.max_pool_size
|
||||
pool_opts.min_pool_size
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ('__max_pool_size', '__min_pool_size',
|
||||
'__max_idle_time_seconds',
|
||||
@ -394,7 +405,7 @@ class PoolOptions(object):
|
||||
return self.__wait_queue_timeout
|
||||
|
||||
@property
|
||||
def ssl_context(self):
|
||||
def _ssl_context(self):
|
||||
"""An SSLContext instance or None.
|
||||
"""
|
||||
return self.__ssl_context
|
||||
@ -406,7 +417,7 @@ class PoolOptions(object):
|
||||
return self.__tls_allow_invalid_hostnames
|
||||
|
||||
@property
|
||||
def event_listeners(self):
|
||||
def _event_listeners(self):
|
||||
"""An instance of pymongo.monitoring._EventListeners.
|
||||
"""
|
||||
return self.__event_listeners
|
||||
@ -424,7 +435,7 @@ class PoolOptions(object):
|
||||
return self.__driver
|
||||
|
||||
@property
|
||||
def compression_settings(self):
|
||||
def _compression_settings(self):
|
||||
return self.__compression_settings
|
||||
|
||||
@property
|
||||
@ -506,9 +517,9 @@ class SocketInfo(object):
|
||||
self.hello_ok = None
|
||||
self.is_mongos = False
|
||||
self.op_msg_enabled = False
|
||||
self.listeners = pool.opts.event_listeners
|
||||
self.listeners = pool.opts._event_listeners
|
||||
self.enabled_for_cmap = pool.enabled_for_cmap
|
||||
self.compression_settings = pool.opts.compression_settings
|
||||
self.compression_settings = pool.opts._compression_settings
|
||||
self.compression_context = None
|
||||
self.socket_checker = SocketChecker()
|
||||
# Support for mechanism negotiation on the initial handshake.
|
||||
@ -1000,7 +1011,7 @@ def _configured_socket(address, options):
|
||||
Sets socket's SSL and timeout options.
|
||||
"""
|
||||
sock = _create_connection(address, options)
|
||||
ssl_context = options.ssl_context
|
||||
ssl_context = options._ssl_context
|
||||
|
||||
if ssl_context is not None:
|
||||
host = address[0]
|
||||
@ -1123,8 +1134,8 @@ class Pool:
|
||||
# Don't publish events in Monitor pools.
|
||||
self.enabled_for_cmap = (
|
||||
self.handshake and
|
||||
self.opts.event_listeners is not None and
|
||||
self.opts.event_listeners.enabled_for_cmap)
|
||||
self.opts._event_listeners is not None and
|
||||
self.opts._event_listeners.enabled_for_cmap)
|
||||
|
||||
# The first portion of the wait queue.
|
||||
# Enforces: maxPoolSize
|
||||
@ -1141,7 +1152,7 @@ class Pool:
|
||||
self._max_connecting = self.opts.max_connecting
|
||||
self._pending = 0
|
||||
if self.enabled_for_cmap:
|
||||
self.opts.event_listeners.publish_pool_created(
|
||||
self.opts._event_listeners.publish_pool_created(
|
||||
self.address, self.opts.non_default_options)
|
||||
# Similar to active_sockets but includes threads in the wait queue.
|
||||
self.operation_count = 0
|
||||
@ -1158,7 +1169,7 @@ class Pool:
|
||||
if self.state != PoolState.READY:
|
||||
self.state = PoolState.READY
|
||||
if self.enabled_for_cmap:
|
||||
self.opts.event_listeners.publish_pool_ready(self.address)
|
||||
self.opts._event_listeners.publish_pool_ready(self.address)
|
||||
|
||||
@property
|
||||
def closed(self):
|
||||
@ -1197,7 +1208,7 @@ class Pool:
|
||||
self._max_connecting_cond.notify_all()
|
||||
self.size_cond.notify_all()
|
||||
|
||||
listeners = self.opts.event_listeners
|
||||
listeners = self.opts._event_listeners
|
||||
# CMAP spec says that close() MUST close sockets before publishing the
|
||||
# PoolClosedEvent but that reset() SHOULD close sockets *after*
|
||||
# publishing the PoolClearedEvent.
|
||||
@ -1301,7 +1312,7 @@ class Pool:
|
||||
conn_id = self.next_connection_id
|
||||
self.next_connection_id += 1
|
||||
|
||||
listeners = self.opts.event_listeners
|
||||
listeners = self.opts._event_listeners
|
||||
if self.enabled_for_cmap:
|
||||
listeners.publish_connection_created(self.address, conn_id)
|
||||
|
||||
@ -1353,7 +1364,7 @@ class Pool:
|
||||
- `all_credentials`: dict, maps auth source to MongoCredential.
|
||||
- `handler` (optional): A _MongoClientErrorHandler.
|
||||
"""
|
||||
listeners = self.opts.event_listeners
|
||||
listeners = self.opts._event_listeners
|
||||
if self.enabled_for_cmap:
|
||||
listeners.publish_connection_check_out_started(self.address)
|
||||
|
||||
@ -1391,7 +1402,7 @@ class Pool:
|
||||
def _raise_if_not_ready(self, emit_event):
|
||||
if self.state != PoolState.READY:
|
||||
if self.enabled_for_cmap and emit_event:
|
||||
self.opts.event_listeners.publish_connection_check_out_failed(
|
||||
self.opts._event_listeners.publish_connection_check_out_failed(
|
||||
self.address, ConnectionCheckOutFailedReason.CONN_ERROR)
|
||||
_raise_connection_failure(
|
||||
self.address, AutoReconnect('connection pool paused'))
|
||||
@ -1406,7 +1417,7 @@ class Pool:
|
||||
|
||||
if self.closed:
|
||||
if self.enabled_for_cmap:
|
||||
self.opts.event_listeners.publish_connection_check_out_failed(
|
||||
self.opts._event_listeners.publish_connection_check_out_failed(
|
||||
self.address, ConnectionCheckOutFailedReason.POOL_CLOSED)
|
||||
raise _PoolClosedError(
|
||||
'Attempted to check out a connection from closed connection '
|
||||
@ -1486,7 +1497,7 @@ class Pool:
|
||||
self.size_cond.notify()
|
||||
|
||||
if self.enabled_for_cmap and not emitted_event:
|
||||
self.opts.event_listeners.publish_connection_check_out_failed(
|
||||
self.opts._event_listeners.publish_connection_check_out_failed(
|
||||
self.address, ConnectionCheckOutFailedReason.CONN_ERROR)
|
||||
raise
|
||||
|
||||
@ -1505,7 +1516,7 @@ class Pool:
|
||||
sock_info.pinned_txn = False
|
||||
sock_info.pinned_cursor = False
|
||||
self.__pinned_sockets.discard(sock_info)
|
||||
listeners = self.opts.event_listeners
|
||||
listeners = self.opts._event_listeners
|
||||
if self.enabled_for_cmap:
|
||||
listeners.publish_connection_checked_in(self.address, sock_info.id)
|
||||
if self.pid != os.getpid():
|
||||
@ -1578,7 +1589,7 @@ class Pool:
|
||||
return False
|
||||
|
||||
def _raise_wait_queue_timeout(self):
|
||||
listeners = self.opts.event_listeners
|
||||
listeners = self.opts._event_listeners
|
||||
if self.enabled_for_cmap:
|
||||
listeners.publish_connection_check_out_failed(
|
||||
self.address, ConnectionCheckOutFailedReason.TIMEOUT)
|
||||
|
||||
@ -73,7 +73,7 @@ class Topology(object):
|
||||
"""Monitor a topology of one or more servers."""
|
||||
def __init__(self, topology_settings):
|
||||
self._topology_id = topology_settings._topology_id
|
||||
self._listeners = topology_settings._pool_options.event_listeners
|
||||
self._listeners = topology_settings._pool_options._event_listeners
|
||||
pub = self._listeners is not None
|
||||
self._publish_server = pub and self._listeners.enabled_for_server
|
||||
self._publish_tp = pub and self._listeners.enabled_for_topology
|
||||
@ -728,9 +728,9 @@ class Topology(object):
|
||||
monitor_pool_options = PoolOptions(
|
||||
connect_timeout=options.connect_timeout,
|
||||
socket_timeout=options.connect_timeout,
|
||||
ssl_context=options.ssl_context,
|
||||
ssl_context=options._ssl_context,
|
||||
tls_allow_invalid_hostnames=options.tls_allow_invalid_hostnames,
|
||||
event_listeners=options.event_listeners,
|
||||
event_listeners=options._event_listeners,
|
||||
appname=options.appname,
|
||||
driver=options.driver,
|
||||
pause_enabled=False,
|
||||
|
||||
@ -44,7 +44,7 @@ def create_test(test_case):
|
||||
self.assertRaises(Exception, MongoClient, uri, connect=False)
|
||||
else:
|
||||
client = MongoClient(uri, connect=False)
|
||||
credentials = client._MongoClient__options.credentials
|
||||
credentials = client._MongoClient__options._credentials
|
||||
if credential is None:
|
||||
self.assertIsNone(credentials)
|
||||
else:
|
||||
|
||||
@ -36,6 +36,7 @@ from bson.son import SON
|
||||
from bson.tz_util import utc
|
||||
import pymongo
|
||||
from pymongo import event_loggers, message, monitoring
|
||||
from pymongo.client_options import ClientOptions
|
||||
from pymongo.command_cursor import CommandCursor
|
||||
from pymongo.common import CONNECT_TIMEOUT, _UUID_REPRESENTATIONS
|
||||
from pymongo.compression_support import _HAVE_SNAPPY, _HAVE_ZSTD
|
||||
@ -56,7 +57,7 @@ from pymongo.hello import HelloCompat
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from pymongo.monitoring import (ServerHeartbeatListener,
|
||||
ServerHeartbeatStartedEvent)
|
||||
from pymongo.pool import SocketInfo, _METADATA
|
||||
from pymongo.pool import SocketInfo, _METADATA, PoolOptions
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.server_description import ServerDescription
|
||||
from pymongo.server_selectors import (readable_server_selector,
|
||||
@ -128,10 +129,10 @@ class ClientUnitTest(unittest.TestCase):
|
||||
# socket.Socket.settimeout takes a float in seconds
|
||||
self.assertEqual(20.0, pool_opts.connect_timeout)
|
||||
self.assertEqual(None, pool_opts.wait_queue_timeout)
|
||||
self.assertEqual(None, pool_opts.ssl_context)
|
||||
self.assertEqual(None, pool_opts._ssl_context)
|
||||
self.assertEqual(None, options.replica_set_name)
|
||||
self.assertEqual(ReadPreference.PRIMARY, client.read_preference)
|
||||
self.assertAlmostEqual(12, client.server_selection_timeout)
|
||||
self.assertAlmostEqual(12, client.options.server_selection_timeout)
|
||||
|
||||
def test_connect_timeout(self):
|
||||
client = MongoClient(connect=False, connectTimeoutMS=None,
|
||||
@ -465,14 +466,23 @@ class ClientUnitTest(unittest.TestCase):
|
||||
|
||||
def test_event_listeners(self):
|
||||
c = MongoClient(event_listeners=[], connect=False)
|
||||
self.assertEqual(c.event_listeners, [])
|
||||
self.assertEqual(c.options.event_listeners, [])
|
||||
listeners = [event_loggers.CommandLogger(),
|
||||
event_loggers.HeartbeatLogger(),
|
||||
event_loggers.ServerLogger(),
|
||||
event_loggers.TopologyLogger(),
|
||||
event_loggers.ConnectionPoolLogger()]
|
||||
c = MongoClient(event_listeners=listeners, connect=False)
|
||||
self.assertEqual(c.event_listeners, listeners)
|
||||
self.assertEqual(c.options.event_listeners, listeners)
|
||||
|
||||
def test_client_options(self):
|
||||
c = MongoClient(connect=False)
|
||||
self.assertIsInstance(c.options, ClientOptions)
|
||||
self.assertIsInstance(c.options.pool_options, PoolOptions)
|
||||
self.assertEqual(c.options.server_selection_timeout, 30)
|
||||
self.assertEqual(c.options.pool_options.max_idle_time_seconds, None)
|
||||
self.assertIsInstance(c.options.retry_writes, bool)
|
||||
self.assertIsInstance(c.options.retry_reads, bool)
|
||||
|
||||
|
||||
class TestClient(IntegrationTest):
|
||||
@ -635,7 +645,7 @@ class TestClient(IntegrationTest):
|
||||
c = rs_or_single_client(connect=False)
|
||||
self.assertIsInstance(c.is_mongos, bool)
|
||||
c = rs_or_single_client(connect=False)
|
||||
self.assertIsInstance(c.max_pool_size, int)
|
||||
self.assertIsInstance(c.options.pool_options.max_pool_size, int)
|
||||
self.assertIsInstance(c.nodes, frozenset)
|
||||
|
||||
c = rs_or_single_client(connect=False)
|
||||
@ -1003,8 +1013,8 @@ class TestClient(IntegrationTest):
|
||||
self.assertEqual(10.5, get_pool(client).opts.connect_timeout)
|
||||
self.assertEqual(10.5, get_pool(client).opts.socket_timeout)
|
||||
self.assertEqual(10.5, get_pool(client).opts.max_idle_time_seconds)
|
||||
self.assertEqual(10500, client.max_idle_time_ms)
|
||||
self.assertEqual(10.5, client.server_selection_timeout)
|
||||
self.assertEqual(10.5, client.options.pool_options.max_idle_time_seconds)
|
||||
self.assertEqual(10.5, client.options.server_selection_timeout)
|
||||
|
||||
def test_socket_timeout_ms_validation(self):
|
||||
c = rs_or_single_client(socketTimeoutMS=10 * 1000)
|
||||
@ -1044,10 +1054,10 @@ class TestClient(IntegrationTest):
|
||||
|
||||
def test_server_selection_timeout(self):
|
||||
client = MongoClient(serverSelectionTimeoutMS=100, connect=False)
|
||||
self.assertAlmostEqual(0.1, client.server_selection_timeout)
|
||||
self.assertAlmostEqual(0.1, client.options.server_selection_timeout)
|
||||
|
||||
client = MongoClient(serverSelectionTimeoutMS=0, connect=False)
|
||||
self.assertAlmostEqual(0, client.server_selection_timeout)
|
||||
self.assertAlmostEqual(0, client.options.server_selection_timeout)
|
||||
|
||||
self.assertRaises(ValueError, MongoClient,
|
||||
serverSelectionTimeoutMS="foo", connect=False)
|
||||
@ -1058,20 +1068,20 @@ class TestClient(IntegrationTest):
|
||||
|
||||
client = MongoClient(
|
||||
'mongodb://localhost/?serverSelectionTimeoutMS=100', connect=False)
|
||||
self.assertAlmostEqual(0.1, client.server_selection_timeout)
|
||||
self.assertAlmostEqual(0.1, client.options.server_selection_timeout)
|
||||
|
||||
client = MongoClient(
|
||||
'mongodb://localhost/?serverSelectionTimeoutMS=0', connect=False)
|
||||
self.assertAlmostEqual(0, client.server_selection_timeout)
|
||||
self.assertAlmostEqual(0, client.options.server_selection_timeout)
|
||||
|
||||
# Test invalid timeout in URI ignored and set to default.
|
||||
client = MongoClient(
|
||||
'mongodb://localhost/?serverSelectionTimeoutMS=-1', connect=False)
|
||||
self.assertAlmostEqual(30, client.server_selection_timeout)
|
||||
self.assertAlmostEqual(30, client.options.server_selection_timeout)
|
||||
|
||||
client = MongoClient(
|
||||
'mongodb://localhost/?serverSelectionTimeoutMS=', connect=False)
|
||||
self.assertAlmostEqual(30, client.server_selection_timeout)
|
||||
self.assertAlmostEqual(30, client.options.server_selection_timeout)
|
||||
|
||||
def test_waitQueueTimeoutMS(self):
|
||||
client = rs_or_single_client(waitQueueTimeoutMS=2000)
|
||||
@ -1379,7 +1389,7 @@ class TestClient(IntegrationTest):
|
||||
def test_compression(self):
|
||||
def compression_settings(client):
|
||||
pool_options = client._MongoClient__options.pool_options
|
||||
return pool_options.compression_settings
|
||||
return pool_options._compression_settings
|
||||
|
||||
uri = "mongodb://localhost:27017/?compressors=zlib"
|
||||
client = MongoClient(uri, connect=False)
|
||||
|
||||
@ -127,7 +127,7 @@ class TestMongosLoadBalancing(MockClientTest):
|
||||
|
||||
def test_local_threshold(self):
|
||||
client = connected(self.mock_client(localThresholdMS=30))
|
||||
self.assertEqual(30, client.local_threshold_ms)
|
||||
self.assertEqual(30, client.options.local_threshold_ms)
|
||||
wait_until(lambda: len(client.nodes) == 3, 'connect to all mongoses')
|
||||
topology = client._topology
|
||||
|
||||
@ -139,7 +139,7 @@ class TestMongosLoadBalancing(MockClientTest):
|
||||
client.admin.command('ping')
|
||||
|
||||
client = connected(self.mock_client(localThresholdMS=0))
|
||||
self.assertEqual(0, client.local_threshold_ms)
|
||||
self.assertEqual(0, client.options.local_threshold_ms)
|
||||
# No error
|
||||
client.db.command('ping')
|
||||
# Our chosen mongos goes down.
|
||||
|
||||
@ -169,7 +169,7 @@ class _TestPoolingBase(IntegrationTest):
|
||||
**kwargs):
|
||||
# Start the pool with the correct ssl options.
|
||||
pool_options = client_context.client._topology_settings.pool_options
|
||||
kwargs['ssl_context'] = pool_options.ssl_context
|
||||
kwargs['ssl_context'] = pool_options._ssl_context
|
||||
kwargs['tls_allow_invalid_hostnames'] = pool_options.tls_allow_invalid_hostnames
|
||||
kwargs['server_api'] = pool_options.server_api
|
||||
pool = Pool(pair, PoolOptions(*args, **kwargs))
|
||||
@ -187,7 +187,7 @@ class TestPooling(_TestPoolingBase):
|
||||
ValueError, MongoClient, host=host, port=port, maxPoolSize='foo')
|
||||
|
||||
c = MongoClient(host=host, port=port, maxPoolSize=100, connect=False)
|
||||
self.assertEqual(c.max_pool_size, 100)
|
||||
self.assertEqual(c.options.pool_options.max_pool_size, 100)
|
||||
|
||||
def test_no_disconnect(self):
|
||||
run_cases(self.c, [NonUnique, Unique, InsertOneAndFind])
|
||||
|
||||
@ -209,20 +209,16 @@ class TestReadPreferences(TestReadPreferencesBase):
|
||||
|
||||
def test_threshold_validation(self):
|
||||
self.assertEqual(17, rs_client(
|
||||
localThresholdMS=17
|
||||
).local_threshold_ms)
|
||||
localThresholdMS=17, connect=False).options.local_threshold_ms)
|
||||
|
||||
self.assertEqual(42, rs_client(
|
||||
localThresholdMS=42
|
||||
).local_threshold_ms)
|
||||
localThresholdMS=42, connect=False).options.local_threshold_ms)
|
||||
|
||||
self.assertEqual(666, rs_client(
|
||||
localthresholdms=666
|
||||
).local_threshold_ms)
|
||||
localThresholdMS=666, connect=False).options.local_threshold_ms)
|
||||
|
||||
self.assertEqual(0, rs_client(
|
||||
localthresholdms=0
|
||||
).local_threshold_ms)
|
||||
localThresholdMS=0, connect=False).options.local_threshold_ms)
|
||||
|
||||
self.assertRaises(ValueError,
|
||||
rs_client,
|
||||
|
||||
@ -48,19 +48,19 @@ _TEST_PATH = os.path.join(
|
||||
class TestClientOptions(PyMongoTestCase):
|
||||
def test_default(self):
|
||||
client = MongoClient(connect=False)
|
||||
self.assertEqual(client.retry_reads, True)
|
||||
self.assertEqual(client.options.retry_reads, True)
|
||||
|
||||
def test_kwargs(self):
|
||||
client = MongoClient(retryReads=True, connect=False)
|
||||
self.assertEqual(client.retry_reads, True)
|
||||
self.assertEqual(client.options.retry_reads, True)
|
||||
client = MongoClient(retryReads=False, connect=False)
|
||||
self.assertEqual(client.retry_reads, False)
|
||||
self.assertEqual(client.options.retry_reads, False)
|
||||
|
||||
def test_uri(self):
|
||||
client = MongoClient('mongodb://h/?retryReads=true', connect=False)
|
||||
self.assertEqual(client.retry_reads, True)
|
||||
self.assertEqual(client.options.retry_reads, True)
|
||||
client = MongoClient('mongodb://h/?retryReads=false', connect=False)
|
||||
self.assertEqual(client.retry_reads, False)
|
||||
self.assertEqual(client.options.retry_reads, False)
|
||||
|
||||
|
||||
class TestSpec(SpecRunner):
|
||||
|
||||
@ -290,7 +290,7 @@ class TestSdamMonitoring(IntegrationTest):
|
||||
'data': data,
|
||||
}
|
||||
with self.fail_point(fail_insert):
|
||||
if self.test_client.retry_writes:
|
||||
if self.test_client.options.retry_writes:
|
||||
self.coll.insert_one({})
|
||||
else:
|
||||
with self.assertRaises(expected_error):
|
||||
|
||||
@ -104,7 +104,7 @@ class TestSession(IntegrationTest):
|
||||
self.assertLessEqual(used_lsids, current_lsids)
|
||||
|
||||
def _test_ops(self, client, *ops):
|
||||
listener = client.event_listeners[0]
|
||||
listener = client.options.event_listeners[0]
|
||||
|
||||
for f, args, kw in ops:
|
||||
with client.start_session() as s:
|
||||
@ -626,7 +626,7 @@ class TestSession(IntegrationTest):
|
||||
lambda cursor: list(cursor))
|
||||
|
||||
def _test_unacknowledged_ops(self, client, *ops):
|
||||
listener = client.event_listeners[0]
|
||||
listener = client.options.event_listeners[0]
|
||||
|
||||
for f, args, kw in ops:
|
||||
with client.start_session() as s:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user