PYTHON-691 - Fix UserWarning command issues.

Don't raise UserWarning for helpers and internal calls to
commands that do not obey read preference.
This commit is contained in:
Bernie Hackett 2014-05-01 09:21:52 -07:00
parent d703ebb832
commit 9d47f1cd3d
16 changed files with 765 additions and 524 deletions

View File

@ -30,6 +30,7 @@ from pymongo import ASCENDING
from pymongo.collection import Collection
from pymongo.cursor import Cursor
from pymongo.errors import DuplicateKeyError
from pymongo.read_preferences import ReadPreference
try:
_SEEK_SET = os.SEEK_SET
@ -258,7 +259,8 @@ class GridIn(object):
db.error()
md5 = db.command(
"filemd5", self._id, root=self._coll.name)["md5"]
"filemd5", self._id, root=self._coll.name,
read_preference=ReadPreference.PRIMARY)["md5"]
self._file["md5"] = md5
self._file["length"] = self._position

View File

@ -28,6 +28,7 @@ from pymongo.cursor import Cursor
from pymongo.errors import InvalidName, OperationFailure
from pymongo.helpers import _check_write_command_response
from pymongo.message import _INSERT, _UPDATE, _DELETE
from pymongo.read_preferences import ReadPreference
try:
@ -125,9 +126,12 @@ class Collection(common.BaseObject):
if options:
if "size" in options:
options["size"] = float(options["size"])
self.__database.command("create", self.__name, **options)
self.__database.command("create", self.__name,
read_preference=ReadPreference.PRIMARY,
**options)
else:
self.__database.command("create", self.__name)
self.__database.command("create", self.__name,
read_preference=ReadPreference.PRIMARY)
def __getattr__(self, name):
"""Get a sub-collection of this collection by name.
@ -1037,7 +1041,9 @@ class Collection(common.BaseObject):
index.update(kwargs)
try:
self.__database.command('createIndexes', self.name, indexes=[index])
self.__database.command('createIndexes', self.name,
read_preference=ReadPreference.PRIMARY,
indexes=[index])
except OperationFailure, exc:
if exc.code in (59, None):
index["ns"] = self.__full_name
@ -1183,7 +1189,9 @@ class Collection(common.BaseObject):
self.__database.connection._purge_index(self.__database.name,
self.__name, name)
self.__database.command("dropIndexes", self.__name, index=name,
self.__database.command("dropIndexes", self.__name,
read_preference=ReadPreference.PRIMARY,
index=name,
allowable_errors=["ns not found"])
def reindex(self):
@ -1195,7 +1203,8 @@ class Collection(common.BaseObject):
.. versionadded:: 1.11+
"""
return self.__database.command("reIndex", self.__name)
return self.__database.command("reIndex", self.__name,
read_preference=ReadPreference.PRIMARY)
def index_information(self):
"""Get information on this collection's indexes.
@ -1416,9 +1425,10 @@ class Collection(common.BaseObject):
raise InvalidName("collection names must not contain '$'")
new_name = "%s.%s" % (self.__database.name, new_name)
self.__database.connection.admin.command("renameCollection",
self.__full_name,
to=new_name, **kwargs)
client = self.__database.connection
client.admin.command("renameCollection", self.__full_name,
read_preference=ReadPreference.PRIMARY,
to=new_name, **kwargs)
def distinct(self, key):
"""Get a list of distinct values for `key` among all documents
@ -1645,6 +1655,7 @@ class Collection(common.BaseObject):
out = self.__database.command("findAndModify", self.__name,
allowable_errors=[no_obj_error],
read_preference=ReadPreference.PRIMARY,
uuid_subtype=self.uuid_subtype,
**kwargs)

View File

@ -26,7 +26,9 @@ from pymongo.errors import (CollectionInvalid,
ConfigurationError,
InvalidName,
OperationFailure)
from pymongo import read_preferences as rp
from pymongo.read_preferences import (modes,
secondary_ok_commands,
ReadPreference)
def _check_name(name):
@ -282,7 +284,7 @@ class Database(common.BaseObject):
command_name = command.keys()[0].lower()
must_use_master = kwargs.pop('_use_master', False)
if command_name not in rp.secondary_ok_commands:
if command_name not in secondary_ok_commands:
must_use_master = True
# Special-case: mapreduce can go to secondaries only if inline
@ -323,13 +325,13 @@ class Database(common.BaseObject):
command.update(kwargs)
# Warn if must_use_master will override read_preference.
if (extra_opts['read_preference'] != rp.ReadPreference.PRIMARY and
if (extra_opts['read_preference'] != ReadPreference.PRIMARY and
extra_opts['_must_use_master']):
warnings.warn("%s does not support %s read preference "
"and will be routed to the primary instead." %
(command_name,
rp.modes[extra_opts['read_preference']]),
UserWarning)
modes[extra_opts['read_preference']]),
UserWarning, stacklevel=3)
cursor = self["$cmd"].find(command, **extra_opts).limit(-1)
for doc in cursor:
@ -466,7 +468,8 @@ class Database(common.BaseObject):
self.__connection._purge_index(self.__name, name)
self.command("drop", unicode(name), allowable_errors=["ns not found"])
self.command("drop", unicode(name), allowable_errors=["ns not found"],
read_preference=ReadPreference.PRIMARY)
def validate_collection(self, name_or_collection,
scandata=False, full=False):
@ -504,7 +507,8 @@ class Database(common.BaseObject):
"%s or Collection" % (basestring.__name__,))
result = self.command("validate", unicode(name),
scandata=scandata, full=full)
scandata=scandata, full=full,
read_preference=ReadPreference.PRIMARY)
valid = True
# Pre 1.9 results
@ -553,7 +557,8 @@ class Database(common.BaseObject):
.. mongodoc:: profiling
"""
result = self.command("profile", -1)
result = self.command("profile", -1,
read_preference=ReadPreference.PRIMARY)
assert result["was"] >= 0 and result["was"] <= 2
return result["was"]
@ -593,9 +598,11 @@ class Database(common.BaseObject):
raise TypeError("slow_ms must be an integer")
if slow_ms is not None:
self.command("profile", level, slowms=slow_ms)
self.command("profile", level, slowms=slow_ms,
read_preference=ReadPreference.PRIMARY)
else:
self.command("profile", level)
self.command("profile", level,
read_preference=ReadPreference.PRIMARY)
def profiling_info(self):
"""Returns a list containing current profiling information.
@ -610,7 +617,8 @@ class Database(common.BaseObject):
Return None if the last operation was error-free. Otherwise return the
error that occurred.
"""
error = self.command("getlasterror")
error = self.command("getlasterror",
read_preference=ReadPreference.PRIMARY)
error_msg = error.get("err", "")
if error_msg is None:
return None
@ -623,7 +631,8 @@ class Database(common.BaseObject):
Returns a SON object with status information.
"""
return self.command("getlasterror")
return self.command("getlasterror",
read_preference=ReadPreference.PRIMARY)
def previous_error(self):
"""Get the most recent error to have occurred on this database.
@ -632,7 +641,8 @@ class Database(common.BaseObject):
`Database.reset_error_history`. Returns None if no such errors have
occurred.
"""
error = self.command("getpreverror")
error = self.command("getpreverror",
read_preference=ReadPreference.PRIMARY)
if error.get("err", 0) is None:
return None
return error
@ -643,7 +653,8 @@ class Database(common.BaseObject):
Calls to `Database.previous_error` will only return errors that have
occurred since the most recent call to this method.
"""
self.command("reseterror")
self.command("reseterror",
read_preference=ReadPreference.PRIMARY)
def __iter__(self):
return self
@ -697,7 +708,8 @@ class Database(common.BaseObject):
else:
command_name = "updateUser"
self.command(command_name, name, **opts)
self.command(command_name, name,
read_preference=ReadPreference.PRIMARY, **opts)
def _legacy_add_user(self, name, password, read_only, **kwargs):
"""Uses v1 system to add users, i.e. saving to system.users.
@ -763,7 +775,8 @@ class Database(common.BaseObject):
"read_only and roles together")
try:
uinfo = self.command("usersInfo", name)
uinfo = self.command("usersInfo", name,
read_preference=ReadPreference.PRIMARY)
except OperationFailure, exc:
# MongoDB >= 2.5.3 requires the use of commands to manage
# users. "No such command" error didn't return an error
@ -793,6 +806,7 @@ class Database(common.BaseObject):
try:
self.command("dropUser", name,
read_preference=ReadPreference.PRIMARY,
writeConcern=self._get_wc_override())
except OperationFailure, exc:
# See comment in add_user try / except above.
@ -930,7 +944,9 @@ class Database(common.BaseObject):
if not isinstance(code, Code):
code = Code(code)
result = self.command("$eval", code, args=args)
result = self.command("$eval", code,
read_preference=ReadPreference.PRIMARY,
args=args)
return result.get("retval", None)
def __call__(self, *args, **kwargs):

View File

@ -61,6 +61,9 @@ from pymongo.errors import (AutoReconnect,
InvalidURI,
OperationFailure)
from pymongo.member import Member
from pymongo.read_preferences import ReadPreference
EMPTY = b("")
@ -1337,13 +1340,15 @@ class MongoClient(common.BaseObject):
def server_info(self):
"""Get information about the MongoDB server we're connected to.
"""
return self.admin.command("buildinfo")
return self.admin.command("buildinfo",
read_preference=ReadPreference.PRIMARY)
def database_names(self):
"""Get a list of the names of all databases on the connected server.
"""
return [db["name"] for db in
self.admin.command("listDatabases")["databases"]]
self.admin.command("listDatabases",
read_preference=ReadPreference.PRIMARY)["databases"]]
def drop_database(self, name_or_database):
"""Drop a database.
@ -1365,7 +1370,8 @@ class MongoClient(common.BaseObject):
"%s or Database" % (basestring.__name__,))
self._purge_index(name)
self[name].command("dropDatabase")
self[name].command("dropDatabase",
read_preference=ReadPreference.PRIMARY)
def copy_database(self, from_name, to_name,
from_host=None, username=None, password=None):
@ -1413,12 +1419,15 @@ class MongoClient(common.BaseObject):
if username is not None:
nonce = self.admin.command("copydbgetnonce",
fromhost=from_host)["nonce"]
read_preference=ReadPreference.PRIMARY,
fromhost=from_host)["nonce"]
command["username"] = username
command["nonce"] = nonce
command["key"] = auth._auth_key(nonce, username, password)
return self.admin.command("copydb", **command)
return self.admin.command("copydb",
read_preference=ReadPreference.PRIMARY,
**command)
finally:
self.end_request()
@ -1467,7 +1476,8 @@ class MongoClient(common.BaseObject):
.. versionadded:: 2.0
"""
self.admin.command("fsync", **kwargs)
self.admin.command("fsync",
read_preference=ReadPreference.PRIMARY, **kwargs)
def unlock(self):
"""Unlock a previously locked server.

View File

@ -59,6 +59,7 @@ from pymongo.errors import (AutoReconnect,
DuplicateKeyError,
OperationFailure,
InvalidOperation)
from pymongo.read_preferences import ReadPreference
from pymongo.thread_util import DummyLock
EMPTY = b("")
@ -1832,13 +1833,15 @@ class MongoReplicaSetClient(common.BaseObject):
def server_info(self):
"""Get information about the MongoDB primary we're connected to.
"""
return self.admin.command("buildinfo")
return self.admin.command("buildinfo",
read_preference=ReadPreference.PRIMARY)
def database_names(self):
"""Get a list of the names of all databases on the connected server.
"""
return [db["name"] for db in
self.admin.command("listDatabases")["databases"]]
self.admin.command("listDatabases",
read_preference=ReadPreference.PRIMARY)["databases"]]
def drop_database(self, name_or_database):
"""Drop a database.
@ -1860,7 +1863,8 @@ class MongoReplicaSetClient(common.BaseObject):
"%s or Database" % (basestring.__name__,))
self._purge_index(name)
self[name].command("dropDatabase")
self[name].command("dropDatabase",
read_preference=ReadPreference.PRIMARY)
def copy_database(self, from_name, to_name,
from_host=None, username=None, password=None):
@ -1906,12 +1910,15 @@ class MongoReplicaSetClient(common.BaseObject):
if username is not None:
nonce = self.admin.command("copydbgetnonce",
fromhost=from_host)["nonce"]
read_preference=ReadPreference.PRIMARY,
fromhost=from_host)["nonce"]
command["username"] = username
command["nonce"] = nonce
command["key"] = auth._auth_key(nonce, username, password)
return self.admin.command("copydb", **command)
return self.admin.command("copydb",
read_preference=ReadPreference.PRIMARY,
**command)
finally:
self.end_request()

View File

@ -22,6 +22,7 @@ import sys
import time
import thread
import unittest
import warnings
sys.path[0:0] = [""]
@ -43,6 +44,7 @@ from pymongo.errors import (AutoReconnect,
from test import version, host, port, pair
from test.pymongo_mocks import MockClient
from test.utils import (assertRaisesExactly,
catch_warnings,
delay,
is_mongos,
remove_all_users,
@ -315,11 +317,16 @@ class TestClient(unittest.TestCase, TestRequestMixin):
def test_from_uri(self):
c = MongoClient(host, port)
self.assertEqual(c, MongoClient("mongodb://%s:%d" % (host, port)))
self.assertTrue(MongoClient(
"mongodb://%s:%d" % (host, port), slave_okay=True).slave_okay)
self.assertTrue(MongoClient(
"mongodb://%s:%d/?slaveok=true;w=2" % (host, port)).slave_okay)
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
self.assertEqual(c, MongoClient("mongodb://%s:%d" % (host, port)))
self.assertTrue(MongoClient(
"mongodb://%s:%d" % (host, port), slave_okay=True).slave_okay)
self.assertTrue(MongoClient(
"mongodb://%s:%d/?slaveok=true;w=2" % (host, port)).slave_okay)
finally:
ctx.exit()
def test_get_default_database(self):
c = MongoClient("mongodb://%s:%d/foo" % (host, port), _connect=False)

View File

@ -51,8 +51,8 @@ from pymongo.errors import (DocumentTooLarge,
OperationFailure,
WTimeoutError)
from test.test_client import get_client
from test.utils import (is_mongos, joinall, enable_text_search, get_pool,
oid_generated_on_client)
from test.utils import (catch_warnings, enable_text_search,
get_pool, is_mongos, joinall, oid_generated_on_client)
from test import (qcheck,
version)
@ -226,19 +226,21 @@ class TestCollection(unittest.TestCase):
def test_deprecated_ttl_index_kwarg(self):
db = self.db
# In Python 2.6+ we could use the catch_warnings context
# manager to test this warning nicely. As we can't do that
# we must test raising errors before the ignore filter is applied.
warnings.simplefilter("error", DeprecationWarning)
ctx = catch_warnings()
try:
warnings.simplefilter("error", DeprecationWarning)
self.assertRaises(DeprecationWarning, lambda:
db.test.ensure_index("goodbye", ttl=10))
finally:
warnings.resetwarnings()
warnings.simplefilter("ignore")
ctx.exit()
self.assertEqual("goodbye_1",
db.test.ensure_index("goodbye", ttl=10))
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
self.assertEqual("goodbye_1",
db.test.ensure_index("goodbye", ttl=10))
finally:
ctx.exit()
self.assertEqual(None, db.test.ensure_index("goodbye"))
def test_ensure_unique_index_threaded(self):
@ -853,10 +855,15 @@ class TestCollection(unittest.TestCase):
)
# Misconfigured value for safe
self.assertRaises(
TypeError,
lambda: db.test.insert([{'i': 2}] * 2, safe=1),
)
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
self.assertRaises(
TypeError,
lambda: db.test.insert([{'i': 2}] * 2, safe=1),
)
finally:
ctx.exit()
def test_insert_iterables(self):
db = self.db
@ -979,10 +986,16 @@ class TestCollection(unittest.TestCase):
db.test.insert({"_id": 2, "x": 2})
# No error
db.test.insert({"_id": 1, "x": 1}, safe=False)
db.test.save({"_id": 1, "x": 1}, safe=False)
db.test.insert({"_id": 2, "x": 2}, safe=False)
db.test.save({"_id": 2, "x": 2}, safe=False)
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
db.test.insert({"_id": 1, "x": 1}, safe=False)
db.test.save({"_id": 1, "x": 1}, safe=False)
db.test.insert({"_id": 2, "x": 2}, safe=False)
db.test.save({"_id": 2, "x": 2}, safe=False)
finally:
ctx.exit()
db.test.insert({"_id": 1, "x": 1}, w=0)
db.test.save({"_id": 1, "x": 1}, w=0)
db.test.insert({"_id": 2, "x": 2}, w=0)
@ -2200,47 +2213,51 @@ class TestCollection(unittest.TestCase):
for j in xrange(5):
c.insert({'j': j, 'i': 0})
sort={'j': DESCENDING}
self.assertEqual(4, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
sort={'j': ASCENDING}
self.assertEqual(0, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
sort=[('j', DESCENDING)]
self.assertEqual(4, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
sort=[('j', ASCENDING)]
self.assertEqual(0, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
sort=SON([('j', DESCENDING)])
self.assertEqual(4, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
sort=SON([('j', ASCENDING)])
self.assertEqual(0, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
ctx = catch_warnings()
try:
from collections import OrderedDict
sort=OrderedDict([('j', DESCENDING)])
warnings.simplefilter("ignore", DeprecationWarning)
sort={'j': DESCENDING}
self.assertEqual(4, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
sort=OrderedDict([('j', ASCENDING)])
sort={'j': ASCENDING}
self.assertEqual(0, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
except ImportError:
pass
# Test that a standard dict with two keys is rejected.
sort={'j': DESCENDING, 'foo': DESCENDING}
self.assertRaises(TypeError, c.find_and_modify, {},
{'$inc': {'i': 1}},
sort=sort)
sort=[('j', DESCENDING)]
self.assertEqual(4, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
sort=[('j', ASCENDING)]
self.assertEqual(0, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
sort=SON([('j', DESCENDING)])
self.assertEqual(4, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
sort=SON([('j', ASCENDING)])
self.assertEqual(0, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
try:
from collections import OrderedDict
sort=OrderedDict([('j', DESCENDING)])
self.assertEqual(4, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
sort=OrderedDict([('j', ASCENDING)])
self.assertEqual(0, c.find_and_modify({},
{'$inc': {'i': 1}},
sort=sort)['j'])
except ImportError:
pass
# Test that a standard dict with two keys is rejected.
sort={'j': DESCENDING, 'foo': DESCENDING}
self.assertRaises(TypeError, c.find_and_modify,
{}, {'$inc': {'i': 1}}, sort=sort)
finally:
ctx.exit()
def test_find_with_nested(self):
if not version.at_least(self.db.connection, (2, 0, 0)):

View File

@ -31,7 +31,7 @@ from pymongo.mongo_client import MongoClient
from pymongo.mongo_replica_set_client import MongoReplicaSetClient
from pymongo.errors import ConfigurationError, OperationFailure
from test import host, port, pair, version
from test.utils import drop_collections
from test.utils import catch_warnings, drop_collections
have_uuid = True
try:
@ -44,11 +44,9 @@ class TestCommon(unittest.TestCase):
def test_baseobject(self):
# In Python 2.6+ we could use the catch_warnings context
# manager to test this warning nicely. As we can't do that
# we must test raising errors before the ignore filter is applied.
warnings.simplefilter("error", UserWarning)
ctx = catch_warnings()
try:
warnings.simplefilter("error", UserWarning)
self.assertRaises(UserWarning, lambda:
MongoClient(host, port, wtimeout=1000, w=0))
try:
@ -61,191 +59,195 @@ class TestCommon(unittest.TestCase):
except UserWarning:
self.fail()
finally:
warnings.resetwarnings()
warnings.simplefilter("ignore")
ctx.exit()
# Connection tests
c = Connection(pair)
self.assertFalse(c.slave_okay)
self.assertFalse(c.safe)
self.assertEqual({}, c.get_lasterror_options())
db = c.pymongo_test
db.drop_collection("test")
self.assertFalse(db.slave_okay)
self.assertFalse(db.safe)
self.assertEqual({}, db.get_lasterror_options())
coll = db.test
self.assertFalse(coll.slave_okay)
self.assertFalse(coll.safe)
self.assertEqual({}, coll.get_lasterror_options())
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
c = Connection(pair)
self.assertFalse(c.slave_okay)
self.assertFalse(c.safe)
self.assertEqual({}, c.get_lasterror_options())
db = c.pymongo_test
db.drop_collection("test")
self.assertFalse(db.slave_okay)
self.assertFalse(db.safe)
self.assertEqual({}, db.get_lasterror_options())
coll = db.test
self.assertFalse(coll.slave_okay)
self.assertFalse(coll.safe)
self.assertEqual({}, coll.get_lasterror_options())
self.assertEqual((False, {}), coll._get_write_mode())
coll.safe = False
coll.write_concern.update(w=1)
self.assertEqual((True, {}), coll._get_write_mode())
coll.write_concern.update(w=3)
self.assertEqual((True, {'w': 3}), coll._get_write_mode())
self.assertEqual((False, {}), coll._get_write_mode())
coll.safe = False
coll.write_concern.update(w=1)
self.assertEqual((True, {}), coll._get_write_mode())
coll.write_concern.update(w=3)
self.assertEqual((True, {'w': 3}), coll._get_write_mode())
coll.safe = True
coll.write_concern.update(w=0)
self.assertEqual((False, {}), coll._get_write_mode())
coll.safe = True
coll.write_concern.update(w=0)
self.assertEqual((False, {}), coll._get_write_mode())
coll = db.test
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
cursor = coll.find(slave_okay=True)
self.assertTrue(cursor._Cursor__slave_okay)
coll = db.test
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
cursor = coll.find(slave_okay=True)
self.assertTrue(cursor._Cursor__slave_okay)
# MongoClient test
c = MongoClient(pair)
self.assertFalse(c.slave_okay)
self.assertTrue(c.safe)
self.assertEqual({}, c.get_lasterror_options())
db = c.pymongo_test
db.drop_collection("test")
self.assertFalse(db.slave_okay)
self.assertTrue(db.safe)
self.assertEqual({}, db.get_lasterror_options())
coll = db.test
self.assertFalse(coll.slave_okay)
self.assertTrue(coll.safe)
self.assertEqual({}, coll.get_lasterror_options())
# MongoClient test
c = MongoClient(pair)
self.assertFalse(c.slave_okay)
self.assertTrue(c.safe)
self.assertEqual({}, c.get_lasterror_options())
db = c.pymongo_test
db.drop_collection("test")
self.assertFalse(db.slave_okay)
self.assertTrue(db.safe)
self.assertEqual({}, db.get_lasterror_options())
coll = db.test
self.assertFalse(coll.slave_okay)
self.assertTrue(coll.safe)
self.assertEqual({}, coll.get_lasterror_options())
self.assertEqual((True, {}), coll._get_write_mode())
coll.safe = False
coll.write_concern.update(w=1)
self.assertEqual((True, {}), coll._get_write_mode())
coll.write_concern.update(w=3)
self.assertEqual((True, {'w': 3}), coll._get_write_mode())
self.assertEqual((True, {}), coll._get_write_mode())
coll.safe = False
coll.write_concern.update(w=1)
self.assertEqual((True, {}), coll._get_write_mode())
coll.write_concern.update(w=3)
self.assertEqual((True, {'w': 3}), coll._get_write_mode())
coll.safe = True
coll.write_concern.update(w=0)
self.assertEqual((False, {}), coll._get_write_mode())
coll.safe = True
coll.write_concern.update(w=0)
self.assertEqual((False, {}), coll._get_write_mode())
coll = db.test
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
cursor = coll.find(slave_okay=True)
self.assertTrue(cursor._Cursor__slave_okay)
coll = db.test
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
cursor = coll.find(slave_okay=True)
self.assertTrue(cursor._Cursor__slave_okay)
# Setting any safe operations overrides explicit safe
self.assertTrue(MongoClient(host, port, wtimeout=1000, safe=False).safe)
# Setting any safe operations overrides explicit safe
self.assertTrue(MongoClient(host, port, wtimeout=1000, safe=False).safe)
c = MongoClient(pair, slaveok=True, w='majority',
wtimeout=300, fsync=True, j=True)
self.assertTrue(c.slave_okay)
self.assertTrue(c.safe)
d = {'w': 'majority', 'wtimeout': 300, 'fsync': True, 'j': True}
self.assertEqual(d, c.get_lasterror_options())
db = c.pymongo_test
self.assertTrue(db.slave_okay)
self.assertTrue(db.safe)
self.assertEqual(d, db.get_lasterror_options())
coll = db.test
self.assertTrue(coll.slave_okay)
self.assertTrue(coll.safe)
self.assertEqual(d, coll.get_lasterror_options())
cursor = coll.find()
self.assertTrue(cursor._Cursor__slave_okay)
cursor = coll.find(slave_okay=False)
self.assertFalse(cursor._Cursor__slave_okay)
c = MongoClient(pair, slaveok=True, w='majority',
wtimeout=300, fsync=True, j=True)
self.assertTrue(c.slave_okay)
self.assertTrue(c.safe)
d = {'w': 'majority', 'wtimeout': 300, 'fsync': True, 'j': True}
self.assertEqual(d, c.get_lasterror_options())
db = c.pymongo_test
self.assertTrue(db.slave_okay)
self.assertTrue(db.safe)
self.assertEqual(d, db.get_lasterror_options())
coll = db.test
self.assertTrue(coll.slave_okay)
self.assertTrue(coll.safe)
self.assertEqual(d, coll.get_lasterror_options())
cursor = coll.find()
self.assertTrue(cursor._Cursor__slave_okay)
cursor = coll.find(slave_okay=False)
self.assertFalse(cursor._Cursor__slave_okay)
c = MongoClient('mongodb://%s/?'
'w=2;wtimeoutMS=300;fsync=true;'
'journal=true' % (pair,))
self.assertTrue(c.safe)
d = {'w': 2, 'wtimeout': 300, 'fsync': True, 'j': True}
self.assertEqual(d, c.get_lasterror_options())
c = MongoClient('mongodb://%s/?'
'w=2;wtimeoutMS=300;fsync=true;'
'journal=true' % (pair,))
self.assertTrue(c.safe)
d = {'w': 2, 'wtimeout': 300, 'fsync': True, 'j': True}
self.assertEqual(d, c.get_lasterror_options())
c = MongoClient('mongodb://%s/?'
'slaveok=true;w=1;wtimeout=300;'
'fsync=true;j=true' % (pair,))
self.assertTrue(c.slave_okay)
self.assertTrue(c.safe)
d = {'w': 1, 'wtimeout': 300, 'fsync': True, 'j': True}
self.assertEqual(d, c.get_lasterror_options())
self.assertEqual(d, c.write_concern)
db = c.pymongo_test
self.assertTrue(db.slave_okay)
self.assertTrue(db.safe)
self.assertEqual(d, db.get_lasterror_options())
self.assertEqual(d, db.write_concern)
coll = db.test
self.assertTrue(coll.slave_okay)
self.assertTrue(coll.safe)
self.assertEqual(d, coll.get_lasterror_options())
self.assertEqual(d, coll.write_concern)
cursor = coll.find()
self.assertTrue(cursor._Cursor__slave_okay)
cursor = coll.find(slave_okay=False)
self.assertFalse(cursor._Cursor__slave_okay)
c = MongoClient('mongodb://%s/?'
'slaveok=true;w=1;wtimeout=300;'
'fsync=true;j=true' % (pair,))
self.assertTrue(c.slave_okay)
self.assertTrue(c.safe)
d = {'w': 1, 'wtimeout': 300, 'fsync': True, 'j': True}
self.assertEqual(d, c.get_lasterror_options())
self.assertEqual(d, c.write_concern)
db = c.pymongo_test
self.assertTrue(db.slave_okay)
self.assertTrue(db.safe)
self.assertEqual(d, db.get_lasterror_options())
self.assertEqual(d, db.write_concern)
coll = db.test
self.assertTrue(coll.slave_okay)
self.assertTrue(coll.safe)
self.assertEqual(d, coll.get_lasterror_options())
self.assertEqual(d, coll.write_concern)
cursor = coll.find()
self.assertTrue(cursor._Cursor__slave_okay)
cursor = coll.find(slave_okay=False)
self.assertFalse(cursor._Cursor__slave_okay)
c.unset_lasterror_options()
self.assertTrue(c.slave_okay)
self.assertTrue(c.safe)
c.safe = False
self.assertFalse(c.safe)
c.slave_okay = False
self.assertFalse(c.slave_okay)
self.assertEqual({}, c.get_lasterror_options())
self.assertEqual({}, c.write_concern)
db = c.pymongo_test
self.assertFalse(db.slave_okay)
self.assertFalse(db.safe)
self.assertEqual({}, db.get_lasterror_options())
self.assertEqual({}, db.write_concern)
coll = db.test
self.assertFalse(coll.slave_okay)
self.assertFalse(coll.safe)
self.assertEqual({}, coll.get_lasterror_options())
self.assertEqual({}, coll.write_concern)
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
cursor = coll.find(slave_okay=True)
self.assertTrue(cursor._Cursor__slave_okay)
c.unset_lasterror_options()
self.assertTrue(c.slave_okay)
self.assertTrue(c.safe)
c.safe = False
self.assertFalse(c.safe)
c.slave_okay = False
self.assertFalse(c.slave_okay)
self.assertEqual({}, c.get_lasterror_options())
self.assertEqual({}, c.write_concern)
db = c.pymongo_test
self.assertFalse(db.slave_okay)
self.assertFalse(db.safe)
self.assertEqual({}, db.get_lasterror_options())
self.assertEqual({}, db.write_concern)
coll = db.test
self.assertFalse(coll.slave_okay)
self.assertFalse(coll.safe)
self.assertEqual({}, coll.get_lasterror_options())
self.assertEqual({}, coll.write_concern)
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
cursor = coll.find(slave_okay=True)
self.assertTrue(cursor._Cursor__slave_okay)
coll.set_lasterror_options(fsync=True)
self.assertEqual({'fsync': True}, coll.get_lasterror_options())
self.assertEqual({'fsync': True}, coll.write_concern)
self.assertEqual({}, db.get_lasterror_options())
self.assertEqual({}, db.write_concern)
self.assertFalse(db.safe)
self.assertEqual({}, c.get_lasterror_options())
self.assertEqual({}, c.write_concern)
self.assertFalse(c.safe)
coll.set_lasterror_options(fsync=True)
self.assertEqual({'fsync': True}, coll.get_lasterror_options())
self.assertEqual({'fsync': True}, coll.write_concern)
self.assertEqual({}, db.get_lasterror_options())
self.assertEqual({}, db.write_concern)
self.assertFalse(db.safe)
self.assertEqual({}, c.get_lasterror_options())
self.assertEqual({}, c.write_concern)
self.assertFalse(c.safe)
db.set_lasterror_options(w='majority')
self.assertEqual({'fsync': True}, coll.get_lasterror_options())
self.assertEqual({'fsync': True}, coll.write_concern)
self.assertEqual({'w': 'majority'}, db.get_lasterror_options())
self.assertEqual({'w': 'majority'}, db.write_concern)
self.assertEqual({}, c.get_lasterror_options())
self.assertEqual({}, c.write_concern)
self.assertFalse(c.safe)
db.slave_okay = True
self.assertTrue(db.slave_okay)
self.assertFalse(c.slave_okay)
self.assertFalse(coll.slave_okay)
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
cursor = db.coll2.find()
self.assertTrue(cursor._Cursor__slave_okay)
cursor = db.coll2.find(slave_okay=False)
self.assertFalse(cursor._Cursor__slave_okay)
db.set_lasterror_options(w='majority')
self.assertEqual({'fsync': True}, coll.get_lasterror_options())
self.assertEqual({'fsync': True}, coll.write_concern)
self.assertEqual({'w': 'majority'}, db.get_lasterror_options())
self.assertEqual({'w': 'majority'}, db.write_concern)
self.assertEqual({}, c.get_lasterror_options())
self.assertEqual({}, c.write_concern)
self.assertFalse(c.safe)
db.slave_okay = True
self.assertTrue(db.slave_okay)
self.assertFalse(c.slave_okay)
self.assertFalse(coll.slave_okay)
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
cursor = db.coll2.find()
self.assertTrue(cursor._Cursor__slave_okay)
cursor = db.coll2.find(slave_okay=False)
self.assertFalse(cursor._Cursor__slave_okay)
self.assertRaises(ConfigurationError, coll.set_lasterror_options, foo=20)
self.assertRaises(TypeError, coll._BaseObject__set_slave_okay, 20)
self.assertRaises(TypeError, coll._BaseObject__set_safe, 20)
self.assertRaises(ConfigurationError, coll.set_lasterror_options, foo=20)
self.assertRaises(TypeError, coll._BaseObject__set_slave_okay, 20)
self.assertRaises(TypeError, coll._BaseObject__set_safe, 20)
coll.remove()
self.assertEqual(None, coll.find_one(slave_okay=True))
coll.unset_lasterror_options()
coll.set_lasterror_options(w=4, wtimeout=10)
# Fails if we don't have 4 active nodes or we don't have replication...
self.assertRaises(OperationFailure, coll.insert, {'foo': 'bar'})
# Succeeds since we override the lasterror settings per query.
self.assertTrue(coll.insert({'foo': 'bar'}, fsync=True))
drop_collections(db)
coll.remove()
self.assertEqual(None, coll.find_one(slave_okay=True))
coll.unset_lasterror_options()
coll.set_lasterror_options(w=4, wtimeout=10)
# Fails if we don't have 4 active nodes or we don't have replication...
self.assertRaises(OperationFailure, coll.insert, {'foo': 'bar'})
# Succeeds since we override the lasterror settings per query.
self.assertTrue(coll.insert({'foo': 'bar'}, fsync=True))
drop_collections(db)
finally:
ctx.exit()
def test_uuid_subtype(self):
if not have_uuid:
@ -439,30 +441,36 @@ class TestCommon(unittest.TestCase):
m = MongoClient(pair, w=0)
coll = m.pymongo_test.write_concern_test
coll.drop()
doc = {"_id": ObjectId()}
coll.insert(doc)
self.assertTrue(coll.insert(doc, safe=False))
self.assertTrue(coll.insert(doc, w=0))
self.assertTrue(coll.insert(doc))
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
m = MongoClient(pair)
coll = m.pymongo_test.write_concern_test
self.assertTrue(coll.insert(doc, safe=False))
self.assertTrue(coll.insert(doc, w=0))
self.assertRaises(OperationFailure, coll.insert, doc)
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
doc = {"_id": ObjectId()}
coll.insert(doc)
self.assertTrue(coll.insert(doc, safe=False))
self.assertTrue(coll.insert(doc, w=0))
self.assertTrue(coll.insert(doc))
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
m = MongoClient("mongodb://%s/" % (pair,))
self.assertTrue(m.safe)
coll = m.pymongo_test.write_concern_test
self.assertRaises(OperationFailure, coll.insert, doc)
m = MongoClient("mongodb://%s/?w=0" % (pair,))
self.assertFalse(m.safe)
coll = m.pymongo_test.write_concern_test
self.assertTrue(coll.insert(doc))
m = MongoClient(pair)
coll = m.pymongo_test.write_concern_test
self.assertTrue(coll.insert(doc, safe=False))
self.assertTrue(coll.insert(doc, w=0))
self.assertRaises(OperationFailure, coll.insert, doc)
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
m = MongoClient("mongodb://%s/" % (pair,))
self.assertTrue(m.safe)
coll = m.pymongo_test.write_concern_test
self.assertRaises(OperationFailure, coll.insert, doc)
m = MongoClient("mongodb://%s/?w=0" % (pair,))
self.assertFalse(m.safe)
coll = m.pymongo_test.write_concern_test
self.assertTrue(coll.insert(doc))
finally:
ctx.exit()
# Equality tests
self.assertEqual(m, MongoClient("mongodb://%s/?w=0" % (pair,)))
@ -478,30 +486,36 @@ class TestCommon(unittest.TestCase):
m = MongoReplicaSetClient(pair, replicaSet=setname, w=0)
coll = m.pymongo_test.write_concern_test
coll.drop()
doc = {"_id": ObjectId()}
coll.insert(doc)
self.assertTrue(coll.insert(doc, safe=False))
self.assertTrue(coll.insert(doc, w=0))
self.assertTrue(coll.insert(doc))
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
m = MongoReplicaSetClient(pair, replicaSet=setname)
coll = m.pymongo_test.write_concern_test
self.assertTrue(coll.insert(doc, safe=False))
self.assertTrue(coll.insert(doc, w=0))
self.assertRaises(OperationFailure, coll.insert, doc)
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
doc = {"_id": ObjectId()}
coll.insert(doc)
self.assertTrue(coll.insert(doc, safe=False))
self.assertTrue(coll.insert(doc, w=0))
self.assertTrue(coll.insert(doc))
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
m = MongoReplicaSetClient("mongodb://%s/?replicaSet=%s" % (pair, setname))
self.assertTrue(m.safe)
coll = m.pymongo_test.write_concern_test
self.assertRaises(OperationFailure, coll.insert, doc)
m = MongoReplicaSetClient("mongodb://%s/?replicaSet=%s;w=0" % (pair, setname))
self.assertFalse(m.safe)
coll = m.pymongo_test.write_concern_test
self.assertTrue(coll.insert(doc))
m = MongoReplicaSetClient(pair, replicaSet=setname)
coll = m.pymongo_test.write_concern_test
self.assertTrue(coll.insert(doc, safe=False))
self.assertTrue(coll.insert(doc, w=0))
self.assertRaises(OperationFailure, coll.insert, doc)
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
m = MongoReplicaSetClient("mongodb://%s/?replicaSet=%s" % (pair, setname))
self.assertTrue(m.safe)
coll = m.pymongo_test.write_concern_test
self.assertRaises(OperationFailure, coll.insert, doc)
m = MongoReplicaSetClient("mongodb://%s/?replicaSet=%s;w=0" % (pair, setname))
self.assertFalse(m.safe)
coll = m.pymongo_test.write_concern_test
self.assertTrue(coll.insert(doc))
finally:
ctx.exit()
if __name__ == "__main__":

View File

@ -19,6 +19,8 @@ import random
import re
import sys
import unittest
import warnings
sys.path[0:0] = [""]
from nose.plugins.skip import SkipTest
@ -37,7 +39,8 @@ from pymongo.errors import (InvalidOperation,
ExecutionTimeout)
from test import version
from test.test_client import get_client
from test.utils import is_mongos, get_command_line, server_started_with_auth
from test.utils import (catch_warnings, is_mongos,
get_command_line, server_started_with_auth)
class TestCursor(unittest.TestCase):
@ -1100,8 +1103,11 @@ self.assertFalse(c2.alive)
pass
client = self.db.connection
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
client.set_cursor_manager(CManager)
docs = []
cursor = self.db.test.find().batch_size(10)
docs.append(cursor.next())
@ -1115,6 +1121,7 @@ self.assertFalse(c2.alive)
self.assertEqual(len(docs), 200)
finally:
client.set_cursor_manager(CursorManager)
ctx.exit()
if __name__ == "__main__":
unittest.main()

View File

@ -47,8 +47,8 @@ from pymongo.son_manipulator import (AutoReference,
NamespaceInjector,
ObjectIdShuffler)
from test import version
from test.utils import (get_command_line, is_mongos,
remove_all_users, server_started_with_auth)
from test.utils import (catch_warnings, get_command_line,
is_mongos, remove_all_users, server_started_with_auth)
from test.test_client import get_client
@ -368,15 +368,15 @@ class TestDatabase(unittest.TestCase):
"user", 'password', True, roles=['read'])
if version.at_least(self.client, (2, 5, 3, -1)):
warnings.simplefilter("error", DeprecationWarning)
ctx = catch_warnings()
try:
warnings.simplefilter("error", DeprecationWarning)
self.assertRaises(DeprecationWarning, db.add_user,
"user", "password")
self.assertRaises(DeprecationWarning, db.add_user,
"user", "password", True)
finally:
warnings.resetwarnings()
warnings.simplefilter("ignore")
ctx.exit()
self.assertRaises(ConfigurationError, db.add_user,
"user", "password", digestPassword=True)
@ -947,8 +947,9 @@ class TestDatabase(unittest.TestCase):
self.fail("_check_command_response didn't raise OperationFailure")
def test_command_read_pref_warning(self):
warnings.simplefilter("error", UserWarning)
ctx = catch_warnings()
try:
warnings.simplefilter("error", UserWarning)
self.assertRaises(UserWarning, self.client.pymongo_test.command,
'ping', read_preference=ReadPreference.SECONDARY)
try:
@ -957,8 +958,7 @@ class TestDatabase(unittest.TestCase):
except UserWarning:
self.fail("Shouldn't have raised UserWarning.")
finally:
warnings.resetwarnings()
warnings.simplefilter("ignore")
ctx.exit()
def test_command_max_time_ms(self):
if not version.at_least(self.client, (2, 5, 3, -1)):

View File

@ -16,25 +16,25 @@
"""Tests for the gridfs package.
"""
import sys
sys.path[0:0] = [""]
from pymongo.mongo_client import MongoClient
from pymongo.errors import ConnectionFailure
from pymongo.read_preferences import ReadPreference
from test.test_replica_set_client import TestReplicaSetClientBase
import datetime
import unittest
import sys
import threading
import time
import unittest
import warnings
sys.path[0:0] = [""]
import gridfs
from bson.py3compat import b, StringIO
from gridfs.errors import (FileExists,
NoFile)
from gridfs.errors import (FileExists, NoFile)
from pymongo.errors import ConnectionFailure
from pymongo.mongo_client import MongoClient
from pymongo.read_preferences import ReadPreference
from test.test_client import get_client
from test.utils import joinall
from test.test_replica_set_client import TestReplicaSetClientBase
from test.utils import catch_warnings, joinall
class JustWrite(threading.Thread):
@ -416,20 +416,25 @@ class TestGridfsReplicaSet(TestReplicaSetClientBase):
primary_connection = MongoClient(primary_host, primary_port)
secondary_host, secondary_port = self.secondaries[0]
for secondary_connection in [
MongoClient(secondary_host, secondary_port, slave_okay=True),
MongoClient(secondary_host, secondary_port,
read_preference=ReadPreference.SECONDARY),
]:
primary_connection.pymongo_test.drop_collection("fs.files")
primary_connection.pymongo_test.drop_collection("fs.chunks")
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
for secondary_connection in [
MongoClient(secondary_host, secondary_port, slave_okay=True),
MongoClient(secondary_host, secondary_port,
read_preference=ReadPreference.SECONDARY),
]:
primary_connection.pymongo_test.drop_collection("fs.files")
primary_connection.pymongo_test.drop_collection("fs.chunks")
# Should detect it's connected to secondary and not attempt to
# create index
fs = gridfs.GridFS(secondary_connection.pymongo_test)
# Should detect it's connected to secondary and not attempt to
# create index
fs = gridfs.GridFS(secondary_connection.pymongo_test)
# This won't detect secondary, raises error
self.assertRaises(ConnectionFailure, fs.put, b('foo'))
# This won't detect secondary, raises error
self.assertRaises(ConnectionFailure, fs.put, b('foo'))
finally:
ctx.exit()
def test_gridfs_secondary_lazy(self):
# Should detect it's connected to secondary and not attempt to

View File

@ -17,6 +17,7 @@
import sys
import unittest
import warnings
sys.path[0:0] = [""]
@ -28,27 +29,33 @@ from pymongo.replica_set_connection import ReplicaSetConnection
from pymongo.errors import ConfigurationError
from test import host, port, pair
from test.test_replica_set_client import TestReplicaSetClientBase
from test.utils import get_pool
from test.utils import catch_warnings, get_pool
class TestConnection(unittest.TestCase):
def test_connection(self):
c = Connection(host, port)
self.assertTrue(c.auto_start_request)
self.assertEqual(None, c.max_pool_size)
self.assertFalse(c.slave_okay)
self.assertFalse(c.safe)
self.assertEqual({}, c.get_lasterror_options())
# Connection's writes are unacknowledged by default
doc = {"_id": ObjectId()}
coll = c.pymongo_test.write_concern_test
coll.drop()
coll.insert(doc)
coll.insert(doc)
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
self.assertTrue(c.auto_start_request)
self.assertEqual(None, c.max_pool_size)
self.assertFalse(c.slave_okay)
self.assertFalse(c.safe)
self.assertEqual({}, c.get_lasterror_options())
c = Connection("mongodb://%s:%s/?safe=true" % (host, port))
self.assertTrue(c.safe)
# Connection's writes are unacknowledged by default
doc = {"_id": ObjectId()}
coll = c.pymongo_test.write_concern_test
coll.drop()
coll.insert(doc)
coll.insert(doc)
c = Connection("mongodb://%s:%s/?safe=true" % (host, port))
self.assertTrue(c.safe)
finally:
ctx.exit()
# To preserve legacy Connection's behavior, max_size should be None.
# Pool should handle this without error.
@ -73,23 +80,29 @@ class TestConnection(unittest.TestCase):
class TestReplicaSetConnection(TestReplicaSetClientBase):
def test_replica_set_connection(self):
c = ReplicaSetConnection(pair, replicaSet=self.name)
self.assertTrue(c.auto_start_request)
self.assertEqual(None, c.max_pool_size)
self.assertFalse(c.slave_okay)
self.assertFalse(c.safe)
self.assertEqual({}, c.get_lasterror_options())
# ReplicaSetConnection's writes are unacknowledged by default
doc = {"_id": ObjectId()}
coll = c.pymongo_test.write_concern_test
coll.drop()
coll.insert(doc)
coll.insert(doc)
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
self.assertTrue(c.auto_start_request)
self.assertEqual(None, c.max_pool_size)
self.assertFalse(c.slave_okay)
self.assertFalse(c.safe)
self.assertEqual({}, c.get_lasterror_options())
c = ReplicaSetConnection("mongodb://%s:%s/?replicaSet=%s&safe=true" % (
host, port, self.name))
# ReplicaSetConnection's writes are unacknowledged by default
doc = {"_id": ObjectId()}
coll = c.pymongo_test.write_concern_test
coll.drop()
coll.insert(doc)
coll.insert(doc)
self.assertTrue(c.safe)
c = ReplicaSetConnection("mongodb://%s:%s/?replicaSet=%s&safe=true" % (
host, port, self.name))
self.assertTrue(c.safe)
finally:
ctx.exit()
# To preserve legacy ReplicaSetConnection's behavior, max_size should
# be None. Pool should handle this without error.

View File

@ -20,6 +20,8 @@ import sys
import threading
import time
import unittest
import warnings
sys.path[0:0] = [""]
from nose.plugins.skip import SkipTest
@ -35,7 +37,7 @@ from pymongo.mongo_client import MongoClient
from pymongo.collection import Collection
from pymongo.master_slave_connection import MasterSlaveConnection
from test import host, port, host2, port2, host3, port3
from test.utils import TestRequestMixin, get_pool
from test.utils import TestRequestMixin, catch_warnings, get_pool
class TestMasterSlaveConnection(unittest.TestCase, TestRequestMixin):
@ -363,7 +365,7 @@ class TestMasterSlaveConnection(unittest.TestCase, TestRequestMixin):
def test_kill_cursor_explicit(self):
c = self.client
c.slave_okay = True
c.read_preference = ReadPreference.SECONDARY_PREFERRED
db = c.pymongo_test
test = db.master_slave_test_kill_cursor_explicit
@ -412,60 +414,65 @@ class TestMasterSlaveConnection(unittest.TestCase, TestRequestMixin):
self.assertRaises(OperationFailure, lambda: list(cursor2))
def test_base_object(self):
c = self.client
self.assertFalse(c.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(c.safe)
self.assertEqual({}, c.get_lasterror_options())
db = c.pymongo_test
self.assertFalse(db.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(db.safe)
self.assertEqual({}, db.get_lasterror_options())
coll = db.test
coll.drop()
self.assertFalse(coll.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(coll.safe)
self.assertEqual({}, coll.get_lasterror_options())
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
self.assertTrue(bool(cursor._Cursor__read_preference))
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
c = self.client
self.assertFalse(c.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(c.safe)
self.assertEqual({}, c.get_lasterror_options())
db = c.pymongo_test
self.assertFalse(db.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(db.safe)
self.assertEqual({}, db.get_lasterror_options())
coll = db.test
coll.drop()
self.assertFalse(coll.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(coll.safe)
self.assertEqual({}, coll.get_lasterror_options())
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
self.assertTrue(bool(cursor._Cursor__read_preference))
w = 1 + len(self.slaves)
wtimeout=10000 # Wait 10 seconds for replication to complete
c.set_lasterror_options(w=w, wtimeout=wtimeout)
self.assertFalse(c.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(c.safe)
self.assertEqual({'w': w, 'wtimeout': wtimeout}, c.get_lasterror_options())
db = c.pymongo_test
self.assertFalse(db.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(db.safe)
self.assertEqual({'w': w, 'wtimeout': wtimeout}, db.get_lasterror_options())
coll = db.test
self.assertFalse(coll.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(coll.safe)
self.assertEqual({'w': w, 'wtimeout': wtimeout},
coll.get_lasterror_options())
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
self.assertTrue(bool(cursor._Cursor__read_preference))
w = 1 + len(self.slaves)
wtimeout=10000 # Wait 10 seconds for replication to complete
c.set_lasterror_options(w=w, wtimeout=wtimeout)
self.assertFalse(c.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(c.safe)
self.assertEqual({'w': w, 'wtimeout': wtimeout}, c.get_lasterror_options())
db = c.pymongo_test
self.assertFalse(db.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(db.safe)
self.assertEqual({'w': w, 'wtimeout': wtimeout}, db.get_lasterror_options())
coll = db.test
self.assertFalse(coll.slave_okay)
self.assertTrue(bool(c.read_preference))
self.assertTrue(coll.safe)
self.assertEqual({'w': w, 'wtimeout': wtimeout},
coll.get_lasterror_options())
cursor = coll.find()
self.assertFalse(cursor._Cursor__slave_okay)
self.assertTrue(bool(cursor._Cursor__read_preference))
coll.insert({'foo': 'bar'})
self.assertEqual(1, coll.find({'foo': 'bar'}).count())
self.assertTrue(coll.find({'foo': 'bar'}))
coll.remove({'foo': 'bar'})
self.assertEqual(0, coll.find({'foo': 'bar'}).count())
coll.insert({'foo': 'bar'})
self.assertEqual(1, coll.find({'foo': 'bar'}).count())
self.assertTrue(coll.find({'foo': 'bar'}))
coll.remove({'foo': 'bar'})
self.assertEqual(0, coll.find({'foo': 'bar'}).count())
c.safe = False
c.unset_lasterror_options()
self.assertFalse(self.client.slave_okay)
self.assertTrue(bool(self.client.read_preference))
self.assertFalse(self.client.safe)
self.assertEqual({}, self.client.get_lasterror_options())
c.safe = False
c.unset_lasterror_options()
self.assertFalse(self.client.slave_okay)
self.assertTrue(bool(self.client.read_preference))
self.assertFalse(self.client.safe)
self.assertEqual({}, self.client.get_lasterror_options())
finally:
ctx.exit()
def test_document_class(self):
c = MasterSlaveConnection(self.master, self.slaves)

View File

@ -14,9 +14,9 @@
"""Test the replica_set_connection module."""
import random
import sys
import unittest
import warnings
from nose.plugins.skip import SkipTest
@ -32,6 +32,7 @@ from pymongo.errors import ConfigurationError
from test.test_replica_set_client import TestReplicaSetClientBase
from test.test_client import get_client
from test import version, utils, host, port
from test.utils import catch_warnings
class TestReadPreferencesBase(TestReplicaSetClientBase):
@ -278,8 +279,13 @@ class TestCommandAndReadPreference(TestReplicaSetClientBase):
# Test generic 'command' method. Some commands obey read preference,
# most don't.
# Disobedient commands, always go to primary
self._test_fn(False, lambda: self.c.pymongo_test.command('ping'))
self._test_fn(False, lambda: self.c.admin.command('buildinfo'))
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", UserWarning)
self._test_fn(False, lambda: self.c.pymongo_test.command('ping'))
self._test_fn(False, lambda: self.c.admin.command('buildinfo'))
finally:
ctx.exit()
# Obedient commands.
self._test_fn(True, lambda: self.c.pymongo_test.command('group', {
@ -342,7 +348,12 @@ class TestCommandAndReadPreference(TestReplicaSetClientBase):
# Text search.
if version.at_least(self.c, (2, 3, 2)):
utils.enable_text_search(self.c)
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", UserWarning)
utils.enable_text_search(self.c)
finally:
ctx.exit()
db = self.c.pymongo_test
# Only way to create an index and wait for all members to build it.
@ -366,20 +377,25 @@ class TestCommandAndReadPreference(TestReplicaSetClientBase):
# Non-inline mapreduce always goes to primary, doesn't obey read prefs.
# Test with command in a SON and with kwargs
self._test_fn(False, lambda: self.c.pymongo_test.command(SON([
('mapreduce', 'test'),
('map', 'function() { }'),
('reduce', 'function() { }'),
('out', 'mr_out')
])))
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", UserWarning)
self._test_fn(False, lambda: self.c.pymongo_test.command(SON([
('mapreduce', 'test'),
('map', 'function() { }'),
('reduce', 'function() { }'),
('out', 'mr_out')
])))
self._test_fn(False, lambda: self.c.pymongo_test.command(
'mapreduce', 'test', map='function() { }',
reduce='function() { }', out='mr_out'))
self._test_fn(False, lambda: self.c.pymongo_test.command(
'mapreduce', 'test', map='function() { }',
reduce='function() { }', out='mr_out'))
self._test_fn(False, lambda: self.c.pymongo_test.command(
'mapreduce', 'test', map='function() { }',
reduce='function() { }', out={'replace': 'some_collection'}))
self._test_fn(False, lambda: self.c.pymongo_test.command(
'mapreduce', 'test', map='function() { }',
reduce='function() { }', out={'replace': 'some_collection'}))
finally:
ctx.exit()
# Inline mapreduce obeys read prefs
self._test_fn(True, lambda: self.c.pymongo_test.command(
@ -405,32 +421,47 @@ class TestCommandAndReadPreference(TestReplicaSetClientBase):
# Aggregate with $out always goes to primary, doesn't obey read prefs.
# Test aggregate command sent directly to db.command.
self._test_fn(False, lambda: self.c.pymongo_test.command(
"aggregate", "test",
pipeline=[{"$match": {"x": 1}}, {"$out": "agg_out"}]
))
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", UserWarning)
self._test_fn(False, lambda: self.c.pymongo_test.command(
"aggregate", "test",
pipeline=[{"$match": {"x": 1}}, {"$out": "agg_out"}]
))
# Test aggregate when sent through the collection aggregate function.
self._test_fn(False, lambda: self.c.pymongo_test.test.aggregate(
[{"$match": {"x": 2}}, {"$out": "agg_out"}]
))
# Test aggregate when sent through the collection aggregate function.
self._test_fn(False, lambda: self.c.pymongo_test.test.aggregate(
[{"$match": {"x": 2}}, {"$out": "agg_out"}]
))
finally:
ctx.exit()
self.c.pymongo_test.drop_collection("test")
self.c.pymongo_test.drop_collection("agg_out")
def test_create_collection(self):
# Collections should be created on primary, obviously
self._test_fn(False, lambda: self.c.pymongo_test.command(
'create', 'some_collection%s' % random.randint(0, sys.maxint)))
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", UserWarning)
self._test_fn(False, lambda: self.c.pymongo_test.command(
'create', 'some_collection%s' % random.randint(0, sys.maxint)))
self._test_fn(False, lambda: self.c.pymongo_test.create_collection(
'some_collection%s' % random.randint(0, sys.maxint)))
self._test_fn(False, lambda: self.c.pymongo_test.create_collection(
'some_collection%s' % random.randint(0, sys.maxint)))
finally:
ctx.exit()
def test_drop_collection(self):
self._test_fn(False, lambda: self.c.pymongo_test.drop_collection(
'some_collection'))
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", UserWarning)
self._test_fn(False, lambda: self.c.pymongo_test.drop_collection(
'some_collection'))
self._test_fn(False, lambda: self.c.pymongo_test.some_collection.drop())
self._test_fn(False, lambda: self.c.pymongo_test.some_collection.drop())
finally:
ctx.exit()
def test_group(self):
self._test_fn(True, lambda: self.c.pymongo_test.test.group(
@ -440,8 +471,13 @@ class TestCommandAndReadPreference(TestReplicaSetClientBase):
# mapreduce fails if no collection
self.c.pymongo_test.test.insert({}, w=self.w)
self._test_fn(False, lambda: self.c.pymongo_test.test.map_reduce(
'function() { }', 'function() { }', 'mr_out'))
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", UserWarning)
self._test_fn(False, lambda: self.c.pymongo_test.test.map_reduce(
'function() { }', 'function() { }', 'mr_out'))
finally:
ctx.exit()
self._test_fn(True, lambda: self.c.pymongo_test.test.map_reduce(
'function() { }', 'function() { }', {'inline': 1}))
@ -517,83 +553,93 @@ class TestMongosConnection(unittest.TestCase):
NEAREST = ReadPreference.NEAREST
SLAVE_OKAY = _QUERY_OPTIONS['slave_okay']
# Test non-PRIMARY modes which can be combined with tags
for kwarg, value, mongos_mode in (
('read_preference', PRIMARY_PREFERRED, 'primaryPreferred'),
('read_preference', SECONDARY, 'secondary'),
('read_preference', SECONDARY_PREFERRED, 'secondaryPreferred'),
('read_preference', NEAREST, 'nearest'),
('slave_okay', True, 'secondaryPreferred'),
('slave_okay', False, 'primary')
):
for tag_sets in (
None, [{}]
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", DeprecationWarning)
# Test non-PRIMARY modes which can be combined with tags
for kwarg, value, mongos_mode in (
('read_preference', PRIMARY_PREFERRED, 'primaryPreferred'),
('read_preference', SECONDARY, 'secondary'),
('read_preference', SECONDARY_PREFERRED, 'secondaryPreferred'),
('read_preference', NEAREST, 'nearest'),
('slave_okay', True, 'secondaryPreferred'),
('slave_okay', False, 'primary')
):
# Create a client e.g. with read_preference=NEAREST or
# slave_okay=True
c = get_client(tag_sets=tag_sets, **{kwarg: value})
for tag_sets in (
None, [{}]
):
# Create a client e.g. with read_preference=NEAREST or
# slave_okay=True
c = get_client(tag_sets=tag_sets, **{kwarg: value})
self.assertEqual(is_mongos, c.is_mongos)
cursor = c.pymongo_test.test.find()
if is_mongos:
# We don't set $readPreference for SECONDARY_PREFERRED
# unless tags are in use. slaveOkay has the same effect.
if mongos_mode == 'secondaryPreferred':
self.assertEqual(
None,
cursor._Cursor__query_spec().get('$readPreference'))
self.assertEqual(is_mongos, c.is_mongos)
cursor = c.pymongo_test.test.find()
if is_mongos:
# We don't set $readPreference for SECONDARY_PREFERRED
# unless tags are in use. slaveOkay has the same effect.
if mongos_mode == 'secondaryPreferred':
self.assertEqual(
None,
cursor._Cursor__query_spec().get('$readPreference'))
self.assertTrue(
cursor._Cursor__query_options() & SLAVE_OKAY)
self.assertTrue(
cursor._Cursor__query_options() & SLAVE_OKAY)
# Don't send $readPreference for PRIMARY either
elif mongos_mode == 'primary':
self.assertEqual(
None,
cursor._Cursor__query_spec().get('$readPreference'))
# Don't send $readPreference for PRIMARY either
elif mongos_mode == 'primary':
self.assertEqual(
None,
cursor._Cursor__query_spec().get('$readPreference'))
self.assertFalse(
cursor._Cursor__query_options() & SLAVE_OKAY)
self.assertFalse(
cursor._Cursor__query_options() & SLAVE_OKAY)
else:
self.assertEqual(
{'mode': mongos_mode},
cursor._Cursor__query_spec().get('$readPreference'))
self.assertTrue(
cursor._Cursor__query_options() & SLAVE_OKAY)
else:
self.assertFalse(
'$readPreference' in cursor._Cursor__query_spec())
for tag_sets in (
[{'dc': 'la'}],
[{'dc': 'la'}, {'dc': 'sf'}],
[{'dc': 'la'}, {'dc': 'sf'}, {}],
):
if kwarg == 'slave_okay':
# Can't use tags with slave_okay True or False, need a
# real read preference
self.assertRaises(
ConfigurationError,
get_client, tag_sets=tag_sets, **{kwarg: value})
continue
c = get_client(tag_sets=tag_sets, **{kwarg: value})
self.assertEqual(is_mongos, c.is_mongos)
cursor = c.pymongo_test.test.find()
if is_mongos:
self.assertEqual(
{'mode': mongos_mode},
{'mode': mongos_mode, 'tags': tag_sets},
cursor._Cursor__query_spec().get('$readPreference'))
self.assertTrue(
cursor._Cursor__query_options() & SLAVE_OKAY)
else:
self.assertFalse(
'$readPreference' in cursor._Cursor__query_spec())
for tag_sets in (
[{'dc': 'la'}],
[{'dc': 'la'}, {'dc': 'sf'}],
[{'dc': 'la'}, {'dc': 'sf'}, {}],
):
if kwarg == 'slave_okay':
# Can't use tags with slave_okay True or False, need a
# real read preference
self.assertRaises(
ConfigurationError,
get_client, tag_sets=tag_sets, **{kwarg: value})
continue
c = get_client(tag_sets=tag_sets, **{kwarg: value})
self.assertEqual(is_mongos, c.is_mongos)
cursor = c.pymongo_test.test.find()
if is_mongos:
self.assertEqual(
{'mode': mongos_mode, 'tags': tag_sets},
cursor._Cursor__query_spec().get('$readPreference'))
else:
self.assertFalse(
'$readPreference' in cursor._Cursor__query_spec())
else:
self.assertFalse(
'$readPreference' in cursor._Cursor__query_spec())
finally:
ctx.exit()
def test_only_secondary_ok_commands_have_read_prefs(self):
c = get_client(read_preference=ReadPreference.SECONDARY)
is_mongos = utils.is_mongos(c)
ctx = catch_warnings()
try:
warnings.simplefilter("ignore", UserWarning)
is_mongos = utils.is_mongos(c)
finally:
ctx.exit()
if not is_mongos:
raise SkipTest("Only mongos have read_prefs added to the spec")

View File

@ -260,7 +260,6 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin):
read_preference=ReadPreference.SECONDARY,
tag_sets=copy.deepcopy(tag_sets),
secondary_acceptable_latency_ms=77)
c.admin.command('ping')
self.assertEqual(c.primary, self.primary)
self.assertEqual(c.hosts, self.hosts)
self.assertEqual(c.arbiters, self.arbiters)

View File

@ -584,3 +584,83 @@ class _TestLazyConnectMixin(object):
self.assertEqual(
ismaster['maxMessageSizeBytes'],
c.max_message_size)
# Backport of WarningMessage from python 2.6, with fixed syntax for python 2.4.
class WarningMessage(object):
"""Holds the result of a single showwarning() call."""
_WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
"line")
def __init__(self, message, category,
filename, lineno, file=None, line=None):
local_values = locals()
for attr in self._WARNING_DETAILS:
setattr(self, attr, local_values[attr])
self._category_name = None
if category:
self._category_name = category.__name__
def __str__(self):
return ("{message : %r, category : %r, filename : %r, lineno : %s, "
"line : %r}" % (self.message, self._category_name,
self.filename, self.lineno, self.line))
# Rough backport of warnings.catch_warnings from python 2.6,
# with changes to support python 2.4.
class CatchWarnings(object):
"""A non-context manager version of warnings.catch_warnings.
The 'record' argument specifies whether warnings should be captured by a
custom implementation of warnings.showwarning() and be appended to a list
accessed through the `log` property. The objects appended to the list are
arguments whose attributes mirror the arguments to showwarning().
The 'module' argument is to specify an alternative module to the module
named 'warnings' and imported under that name. This argument is only useful
when testing the warnings module itself.
"""
def __init__(self, record=False, module=None):
self._record = record
if module is None:
self._module = sys.modules['warnings']
else:
self._module = module
# No __enter__ so do that work here
self._filters = self._module.filters
self._module.filters = self._filters[:]
self._showwarning = self._module.showwarning
self._log = []
if self._record:
def showwarning(*args, **kwargs):
self._log.append(WarningMessage(*args, **kwargs))
self._module.showwarning = showwarning
@property
def log(self):
"""A list of any warnings recorded when using record=True."""
return self._log
def __repr__(self):
args = []
if self._record:
args.append("record=True")
if self._module is not sys.modules['warnings']:
args.append("module=%r" % self._module)
name = type(self).__name__
return "%s(%s)" % (name, ", ".join(args))
def exit(self):
"""Revert changes to the warnings module."""
self._module.filters = self._filters
self._module.showwarning = self._showwarning
def catch_warnings(record=False, module=None):
"""Helper for use with CatchWarnings."""
return CatchWarnings(record, module)