PYTHON-851 - Clean up MongoClient properties.
This commit is contained in:
parent
f2aa319f22
commit
6bacdaafaa
@ -43,7 +43,7 @@ class CodecOptions(_options_base):
|
||||
def __new__(cls, as_class=dict,
|
||||
tz_aware=False, uuid_representation=PYTHON_LEGACY):
|
||||
if not issubclass(as_class, MutableMapping):
|
||||
raise TypeError("document_class must be dict, bson.son.SON, or "
|
||||
raise TypeError("as_class must be dict, bson.son.SON, or "
|
||||
"another subclass of collections.MutableMapping")
|
||||
if not isinstance(tz_aware, bool):
|
||||
raise TypeError("tz_aware must be True or False")
|
||||
|
||||
@ -15,14 +15,10 @@
|
||||
Raises :class:`~pymongo.errors.InvalidName` if an invalid database name is used.
|
||||
|
||||
.. autoattribute:: address
|
||||
.. autoattribute:: host
|
||||
.. autoattribute:: port
|
||||
.. autoattribute:: is_primary
|
||||
.. autoattribute:: is_mongos
|
||||
.. autoattribute:: max_pool_size
|
||||
.. autoattribute:: nodes
|
||||
.. autoattribute:: document_class
|
||||
.. autoattribute:: tz_aware
|
||||
.. autoattribute:: max_bson_size
|
||||
.. autoattribute:: max_message_size
|
||||
.. autoattribute:: min_wire_version
|
||||
|
||||
@ -17,10 +17,7 @@
|
||||
.. autoattribute:: primary
|
||||
.. autoattribute:: secondaries
|
||||
.. autoattribute:: arbiters
|
||||
.. autoattribute:: is_mongos
|
||||
.. autoattribute:: max_pool_size
|
||||
.. autoattribute:: document_class
|
||||
.. autoattribute:: tz_aware
|
||||
.. autoattribute:: max_bson_size
|
||||
.. autoattribute:: max_message_size
|
||||
.. autoattribute:: min_wire_version
|
||||
@ -32,4 +29,7 @@
|
||||
.. automethod:: database_names
|
||||
.. automethod:: drop_database
|
||||
.. automethod:: get_default_database
|
||||
.. automethod:: get_database
|
||||
.. automethod:: close_cursor
|
||||
.. automethod:: kill_cursors
|
||||
.. automethod:: set_cursor_manager
|
||||
|
||||
@ -87,6 +87,9 @@ The ``copy_database`` method is removed, see the
|
||||
The ``disconnect`` method is removed. Use
|
||||
:meth:`~pymongo.mongo_client.MongoClient.close` instead.
|
||||
|
||||
The ``get_document_class`` method is removed. Use
|
||||
:attr:`~pymongo.mongo_client.MongoClient.codec_options` instead.
|
||||
|
||||
The ``get_lasterror_options``, ``set_lasterror_options``, and
|
||||
``unset_lasterror_options`` methods are removed. Write concern options
|
||||
can be passed to :class:`~pymongo.mongo_client.MongoClient` as keyword
|
||||
@ -96,7 +99,7 @@ The :meth:`~pymongo.mongo_client.MongoClient.get_database` method is added for
|
||||
getting a Database instance with its options configured differently than the
|
||||
MongoClient's.
|
||||
|
||||
The following attributes have been added:
|
||||
The following read-only attributes have been added:
|
||||
|
||||
- :attr:`~pymongo.mongo_client.MongoClient.codec_options`
|
||||
|
||||
@ -107,9 +110,17 @@ The following attributes are now read-only:
|
||||
|
||||
The following attributes have been removed:
|
||||
|
||||
- :attr:`~pymongo.mongo_client.MongoClient.document_class`
|
||||
(use :attr:`~pymongo.mongo_client.MongoClient.codec_options` instead)
|
||||
- :attr:`~pymongo.mongo_client.MongoClient.host`
|
||||
(use :attr:`~pymongo.mongo_client.MongoClient.address` instead)
|
||||
- :attr:`~pymongo.mongo_client.MongoClient.port`
|
||||
(use :attr:`~pymongo.mongo_client.MongoClient.address` instead)
|
||||
- :attr:`~pymongo.mongo_client.MongoClient.safe`
|
||||
- :attr:`~pymongo.mongo_client.MongoClient.slave_okay`
|
||||
- :attr:`~pymongo.mongo_client.MongoClient.tag_sets`
|
||||
- :attr:`~pymongo.mongo_client.MongoClient.tz_aware`
|
||||
(use :attr:`~pymongo.mongo_client.MongoClient.codec_options` instead)
|
||||
|
||||
The following attributes have been renamed:
|
||||
|
||||
@ -143,7 +154,7 @@ parameter.
|
||||
The ``connection`` property is renamed to
|
||||
:attr:`~pymongo.database.Database.client`.
|
||||
|
||||
The following attributes have been added:
|
||||
The following read-only attributes have been added:
|
||||
|
||||
- :attr:`~pymongo.database.Database.codec_options`
|
||||
|
||||
@ -192,7 +203,7 @@ The ``get_lasterror_options``, ``set_lasterror_options``, and
|
||||
:class:`~pymongo.collection.Collection` changes
|
||||
...............................................
|
||||
|
||||
The following attributes have been added:
|
||||
The following read-only attributes have been added:
|
||||
|
||||
- :attr:`~pymongo.collection.Collection.codec_options`
|
||||
|
||||
|
||||
@ -264,7 +264,7 @@ class MongoClient(common.BaseObject):
|
||||
|
||||
client['__my_database__']
|
||||
|
||||
Not:
|
||||
Not::
|
||||
|
||||
client.__my_database__
|
||||
"""
|
||||
@ -462,28 +462,6 @@ class MongoClient(common.BaseObject):
|
||||
except ConnectionFailure:
|
||||
return default
|
||||
|
||||
@property
|
||||
def host(self):
|
||||
"""Hostname of the standalone, primary, or mongos currently in use.
|
||||
|
||||
.. warning:: An application that accesses :attr:`host` and :attr:`port`
|
||||
is vulnerable to a race condition, if the client switches to a
|
||||
new primary or mongos in between. Use :attr:`address` instead.
|
||||
"""
|
||||
address = self.address
|
||||
return address[0] if address else None
|
||||
|
||||
@property
|
||||
def port(self):
|
||||
"""Port of the standalone, primary, or mongos currently in use.
|
||||
|
||||
.. warning:: An application that accesses :attr:`host` and :attr:`port`
|
||||
is vulnerable to a race condition, if the client switches to a
|
||||
new primary or mongos in between. Use :attr:`address` instead.
|
||||
"""
|
||||
address = self.address
|
||||
return address[1] if address else None
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
"""(host, port) of the current standalone, primary, or mongos, or None.
|
||||
@ -506,7 +484,9 @@ class MongoClient(common.BaseObject):
|
||||
def primary(self):
|
||||
"""The (host, port) of the current primary of the replica set.
|
||||
|
||||
Returns None if there is no primary.
|
||||
Returns ``None`` if this client is not connected to a replica set,
|
||||
there is no primary, or this client was created without the
|
||||
`replicaSet` option.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
MongoClient gained this property in version 3.0 when
|
||||
@ -518,7 +498,9 @@ class MongoClient(common.BaseObject):
|
||||
def secondaries(self):
|
||||
"""The secondary members known to this client.
|
||||
|
||||
A sequence of (host, port) pairs.
|
||||
A sequence of (host, port) pairs. Empty if this client is not
|
||||
connected to a replica set, there are no visible secondaries, or this
|
||||
client was created without the `replicaSet` option.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
MongoClient gained this property in version 3.0 when
|
||||
@ -531,13 +513,14 @@ class MongoClient(common.BaseObject):
|
||||
"""Arbiters in the replica set.
|
||||
|
||||
A sequence of (host, port) pairs. Empty if this client is not
|
||||
connected to a replica set.
|
||||
connected to a replica set, there are no arbiters, or this client was
|
||||
created without the `replicaSet` option.
|
||||
"""
|
||||
return self._topology.get_arbiters()
|
||||
|
||||
@property
|
||||
def is_primary(self):
|
||||
"""If the current server can accept writes.
|
||||
"""If this client if connected to a server that can accept writes.
|
||||
|
||||
True if the current server is a standalone, mongos, or the primary of
|
||||
a replica set.
|
||||
@ -571,32 +554,6 @@ class MongoClient(common.BaseObject):
|
||||
description = self._topology.description
|
||||
return frozenset(s.address for s in description.known_servers)
|
||||
|
||||
@property
|
||||
def document_class(self):
|
||||
"""Default class to use for documents returned from this client.
|
||||
|
||||
.. versionchanged:: 3.0
|
||||
Now read-only.
|
||||
"""
|
||||
return self.__options.codec_options.as_class
|
||||
|
||||
def get_document_class(self):
|
||||
"""Default class to use for documents returned from this client.
|
||||
|
||||
Deprecated; use the document_class property instead.
|
||||
"""
|
||||
warnings.warn('get_document_class() is deprecated, use the'
|
||||
' document_class property',
|
||||
DeprecationWarning, stacklevel=2)
|
||||
|
||||
return self.__options.codec_options.as_class
|
||||
|
||||
@property
|
||||
def tz_aware(self):
|
||||
"""Does this client return timezone-aware datetimes?
|
||||
"""
|
||||
return self.__options.codec_options.tz_aware
|
||||
|
||||
@property
|
||||
def max_bson_size(self):
|
||||
"""The largest BSON object the connected server accepts in bytes.
|
||||
|
||||
@ -178,7 +178,7 @@ class Topology(object):
|
||||
topology_type = self._description.topology_type
|
||||
if topology_type not in (TOPOLOGY_TYPE.ReplicaSetWithPrimary,
|
||||
TOPOLOGY_TYPE.ReplicaSetNoPrimary):
|
||||
return []
|
||||
return set()
|
||||
|
||||
descriptions = selector(self._description.known_servers)
|
||||
return set([d.address for d in descriptions])
|
||||
|
||||
@ -206,16 +206,11 @@ class TestClient(IntegrationTest):
|
||||
self.assertIsInstance(c.max_pool_size, int)
|
||||
self.assertIsInstance(c.nodes, frozenset)
|
||||
|
||||
with ignore_deprecations():
|
||||
self.assertEqual(dict, c.get_document_class())
|
||||
|
||||
self.assertIsInstance(c.tz_aware, bool)
|
||||
self.assertEqual(c.codec_options, CodecOptions())
|
||||
self.assertIsInstance(c.max_bson_size, int)
|
||||
self.assertIsInstance(c.min_wire_version, int)
|
||||
self.assertIsInstance(c.max_wire_version, int)
|
||||
self.assertIsInstance(c.max_write_batch_size, int)
|
||||
self.assertEqual(None, c.host)
|
||||
self.assertEqual(None, c.port)
|
||||
self.assertFalse(c.primary)
|
||||
self.assertFalse(c.secondaries)
|
||||
|
||||
@ -272,8 +267,7 @@ class TestClient(IntegrationTest):
|
||||
self.assertIn("%s:%d" % node, repr(self.client))
|
||||
|
||||
def test_getters(self):
|
||||
self.assertEqual(client_context.client.host, host)
|
||||
self.assertEqual(client_context.client.port, port)
|
||||
self.assertEqual(client_context.client.address, (host, port))
|
||||
self.assertEqual(client_context.nodes, self.client.nodes)
|
||||
|
||||
def test_database_names(self):
|
||||
@ -470,23 +464,16 @@ class TestClient(IntegrationTest):
|
||||
db = c.pymongo_test
|
||||
db.test.insert_one({"x": 1})
|
||||
|
||||
self.assertEqual(dict, c.document_class)
|
||||
self.assertEqual(dict, c.codec_options.as_class)
|
||||
self.assertTrue(isinstance(db.test.find_one(), dict))
|
||||
self.assertFalse(isinstance(db.test.find_one(), SON))
|
||||
|
||||
c = rs_or_single_client(document_class=SON)
|
||||
db = c.pymongo_test
|
||||
|
||||
self.assertEqual(SON, c.document_class)
|
||||
self.assertEqual(SON, c.codec_options.as_class)
|
||||
self.assertTrue(isinstance(db.test.find_one(), SON))
|
||||
|
||||
# document_class is read-only in PyMongo 3.0.
|
||||
with self.assertRaises(AttributeError):
|
||||
c.document_class = dict
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error", DeprecationWarning)
|
||||
self.assertRaises(DeprecationWarning, c.get_document_class)
|
||||
|
||||
def test_timeouts(self):
|
||||
client = rs_or_single_client(connectTimeoutMS=10500)
|
||||
@ -1070,8 +1057,7 @@ class TestMongoClientFailover(MockClientTest):
|
||||
replicaSet='rs')
|
||||
|
||||
wait_until(lambda: len(c.nodes) == 3, 'connect')
|
||||
self.assertEqual('a', c.host)
|
||||
self.assertEqual(1, c.port)
|
||||
self.assertEqual(c.address, ('a', 1))
|
||||
|
||||
# Fail over.
|
||||
c.kill_host('a:1')
|
||||
@ -1082,8 +1068,7 @@ class TestMongoClientFailover(MockClientTest):
|
||||
|
||||
t = c._get_topology()
|
||||
t.select_servers(writable_server_selector) # Reconnect.
|
||||
self.assertEqual('b', c.host)
|
||||
self.assertEqual(2, c.port)
|
||||
self.assertEqual(c.address, ('b', 2))
|
||||
|
||||
# a:1 not longer in nodes.
|
||||
self.assertLess(len(c.nodes), 3)
|
||||
@ -1113,8 +1098,7 @@ class TestMongoClientFailover(MockClientTest):
|
||||
# But it can reconnect.
|
||||
c.revive_host('a:1')
|
||||
c._get_topology().select_servers(writable_server_selector)
|
||||
self.assertEqual('a', c.host)
|
||||
self.assertEqual(1, c.port)
|
||||
self.assertEqual(c.address, ('a', 1))
|
||||
|
||||
def test_network_error_on_operation(self):
|
||||
# Verify only the disconnected server is reset by a network failure.
|
||||
|
||||
@ -21,6 +21,7 @@ import time
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
from bson.codec_options import CodecOptions
|
||||
from bson.py3compat import u
|
||||
from bson.son import SON
|
||||
from pymongo.common import partition_node
|
||||
@ -124,12 +125,11 @@ class TestReplicaSetClient(TestReplicaSetClientBase):
|
||||
self.assertEqual(c.secondaries, self.secondaries)
|
||||
self.assertEqual(c.arbiters, self.arbiters)
|
||||
self.assertEqual(c.max_pool_size, 100)
|
||||
self.assertEqual(c.document_class, dict)
|
||||
self.assertEqual(c.tz_aware, False)
|
||||
|
||||
# Make sure MongoClient's properties are copied to Database and
|
||||
# Collection.
|
||||
for obj in c, c.pymongo_test, c.pymongo_test.test:
|
||||
self.assertEqual(obj.codec_options, CodecOptions())
|
||||
self.assertEqual(obj.read_preference, ReadPreference.PRIMARY)
|
||||
self.assertEqual(obj.write_concern, WriteConcern())
|
||||
|
||||
@ -143,14 +143,14 @@ class TestReplicaSetClient(TestReplicaSetClientBase):
|
||||
pair, replicaSet=self.name, max_pool_size=25,
|
||||
document_class=SON, tz_aware=True,
|
||||
read_preference=secondary,
|
||||
localThresholdMS=77)
|
||||
localThresholdMS=77, j=True)
|
||||
|
||||
self.assertEqual(c.max_pool_size, 25)
|
||||
self.assertEqual(c.document_class, SON)
|
||||
self.assertEqual(c.tz_aware, True)
|
||||
|
||||
for obj in c, c.pymongo_test, c.pymongo_test.test:
|
||||
self.assertEqual(obj.codec_options, CodecOptions(SON, True))
|
||||
self.assertEqual(obj.read_preference, secondary)
|
||||
self.assertEqual(obj.write_concern, WriteConcern(j=True))
|
||||
|
||||
cursor = c.pymongo_test.test.find()
|
||||
self.assertEqual(
|
||||
|
||||
@ -43,8 +43,8 @@ class TestSecondaryBecomesStandalone(MockClientTest):
|
||||
replicaSet='rs')
|
||||
|
||||
# MongoClient connects to primary by default.
|
||||
wait_until(lambda: c.host == 'a', 'connect to primary')
|
||||
self.assertEqual(1, c.port)
|
||||
wait_until(lambda: c.address is not None, 'connect to primary')
|
||||
self.assertEqual(c.address, ('a', 1))
|
||||
|
||||
# C is brought up as a standalone.
|
||||
c.mock_members.remove('c:3')
|
||||
@ -60,8 +60,7 @@ class TestSecondaryBecomesStandalone(MockClientTest):
|
||||
with self.assertRaises(AutoReconnect):
|
||||
c.db.command('ismaster')
|
||||
|
||||
self.assertEqual(None, c.host)
|
||||
self.assertEqual(None, c.port)
|
||||
self.assertEqual(c.address, None)
|
||||
|
||||
def test_replica_set_client(self):
|
||||
c = MockClient(
|
||||
@ -144,8 +143,7 @@ class TestSecondaryAdded(MockClientTest):
|
||||
wait_until(lambda: len(c.nodes) == 2, 'discover both nodes')
|
||||
|
||||
# MongoClient connects to primary by default.
|
||||
self.assertEqual('a', c.host)
|
||||
self.assertEqual(1, c.port)
|
||||
self.assertEqual(c.address, ('a', 1))
|
||||
self.assertEqual(set([('a', 1), ('b', 2)]), c.nodes)
|
||||
|
||||
# C is added.
|
||||
@ -155,8 +153,7 @@ class TestSecondaryAdded(MockClientTest):
|
||||
c.close()
|
||||
c.db.command('ismaster')
|
||||
|
||||
self.assertEqual('a', c.host)
|
||||
self.assertEqual(1, c.port)
|
||||
self.assertEqual(c.address, ('a', 1))
|
||||
|
||||
wait_until(lambda: set([('a', 1), ('b', 2), ('c', 3)]) == c.nodes,
|
||||
'reconnect to both secondaries')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user