PYTHON-851 - Clean up MongoClient properties.

This commit is contained in:
Bernie Hackett 2015-03-08 20:23:07 -07:00
parent f2aa319f22
commit 6bacdaafaa
9 changed files with 46 additions and 101 deletions

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -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`

View File

@ -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.

View File

@ -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])

View File

@ -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.

View File

@ -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(

View File

@ -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')