PYTHON-526 Remove the "safe" option.

Use w=0 for unacknowledged write operations.
This commit is contained in:
Bernie Hackett 2014-04-04 17:15:50 -07:00
parent e08aa1f90d
commit 85db128efd
13 changed files with 44 additions and 195 deletions

View File

@ -28,10 +28,10 @@
.. autoattribute:: secondary_acceptable_latency_ms
.. autoattribute:: write_concern
.. autoattribute:: uuid_subtype
.. automethod:: insert(doc_or_docs[, manipulate=True[, safe=None[, check_keys=True[, continue_on_error=False[, **kwargs]]]]])
.. automethod:: save(to_save[, manipulate=True[, safe=None[, check_keys=True[, **kwargs]]]])
.. automethod:: update(spec, document[, upsert=False[, manipulate=False[, safe=None[, multi=False[, check_keys=True[, **kwargs]]]]]])
.. automethod:: remove([spec_or_id=None[, safe=None[, multi=True[, **kwargs]]]])
.. automethod:: insert(doc_or_docs[, manipulate=True[, check_keys=True[, continue_on_error=False[, **kwargs]]]])
.. automethod:: save(to_save[, manipulate=True[, check_keys=True[, **kwargs]]])
.. automethod:: update(spec, document[, upsert=False[, manipulate=False[, multi=False[, check_keys=True[, **kwargs]]]]])
.. automethod:: remove([spec_or_id=None[, multi=True[, **kwargs]]])
.. automethod:: initialize_unordered_bulk_op
.. automethod:: initialize_ordered_bulk_op
.. automethod:: drop
@ -53,7 +53,6 @@
.. automethod:: map_reduce
.. automethod:: inline_map_reduce
.. automethod:: find_and_modify
.. autoattribute:: safe
.. automethod:: get_lasterror_options
.. automethod:: set_lasterror_options
.. automethod:: unset_lasterror_options

View File

@ -28,7 +28,6 @@
.. autoattribute:: secondary_acceptable_latency_ms
.. autoattribute:: write_concern
.. autoattribute:: uuid_subtype
.. autoattribute:: safe
.. automethod:: get_lasterror_options
.. automethod:: set_lasterror_options
.. automethod:: unset_lasterror_options

View File

@ -7,7 +7,6 @@
.. autoclass:: pymongo.master_slave_connection.MasterSlaveConnection
:members:
.. autoattribute:: safe
.. automethod:: get_lasterror_options
.. automethod:: set_lasterror_options
.. automethod:: unset_lasterror_options

View File

@ -89,7 +89,7 @@ the previous example more terse:
... {'region': region, 'browser': browser, 'os': os},
... {'$inc': {'n': 1 }},
... upsert=True,
... safe=False)
... w=0)
... print sum([p['n'] for p in counts.find({'region': region})])
2
>>> client.in_request() # request automatically ended

View File

@ -90,7 +90,6 @@ class Collection(common.BaseObject):
tag_sets=database.tag_sets,
secondary_acceptable_latency_ms=(
database.secondary_acceptable_latency_ms),
safe=database.safe,
uuidrepresentation=database.uuid_subtype,
**database.write_concern)
@ -213,8 +212,7 @@ class Collection(common.BaseObject):
"""
return bulk.BulkOperationBuilder(self, ordered=True)
def save(self, to_save, manipulate=True,
safe=None, check_keys=True, **kwargs):
def save(self, to_save, manipulate=True, check_keys=True, **kwargs):
"""Save a document in this collection.
If `to_save` already has an ``"_id"`` then an :meth:`update`
@ -243,7 +241,6 @@ class Collection(common.BaseObject):
- `to_save`: the document to be saved
- `manipulate` (optional): manipulate the document before
saving it?
- `safe` (optional): **DEPRECATED** - Use `w` instead.
- `check_keys` (optional): check if keys start with '$' or
contain '.', raising :class:`~pymongo.errors.InvalidName`
in either case.
@ -267,6 +264,8 @@ class Collection(common.BaseObject):
- The ``'_id'`` value of `to_save` or ``[None]`` if `manipulate` is
``False`` and `to_save` has no '_id' field.
.. versionchanged:: 3.0
Removed the `safe` parameter
.. versionadded:: 1.8
Support for passing `getLastError` options as keyword
arguments.
@ -277,14 +276,14 @@ class Collection(common.BaseObject):
raise TypeError("cannot save object of type %s" % type(to_save))
if "_id" not in to_save:
return self.insert(to_save, manipulate, safe, check_keys, **kwargs)
return self.insert(to_save, manipulate, check_keys, **kwargs)
else:
self.update({"_id": to_save["_id"]}, to_save, True,
manipulate, safe, check_keys=check_keys, **kwargs)
manipulate, check_keys=check_keys, **kwargs)
return to_save.get("_id", None)
def insert(self, doc_or_docs, manipulate=True,
safe=None, check_keys=True, continue_on_error=False, **kwargs):
check_keys=True, continue_on_error=False, **kwargs):
"""Insert a document(s) into this collection.
If `manipulate` is ``True``, the document(s) are manipulated using
@ -312,7 +311,6 @@ class Collection(common.BaseObject):
inserted
- `manipulate` (optional): If ``True`` manipulate the documents
before inserting.
- `safe` (optional): **DEPRECATED** - Use `w` instead.
- `check_keys` (optional): If ``True`` check if keys start with '$'
or contain '.', raising :class:`~pymongo.errors.InvalidName` in
either case.
@ -345,6 +343,8 @@ class Collection(common.BaseObject):
.. note:: `continue_on_error` requires server version **>= 1.9.1**
.. versionchanged:: 3.0
Removed the `safe` parameter
.. versionadded:: 2.1
Support for continue_on_error.
.. versionadded:: 1.8
@ -386,7 +386,7 @@ class Collection(common.BaseObject):
ids.append(doc.get('_id'))
yield doc
safe, options = self._get_write_mode(safe, **kwargs)
safe, options = self._get_write_mode(kwargs)
if client.max_wire_version > 1 and safe:
# Insert command
@ -412,7 +412,7 @@ class Collection(common.BaseObject):
return ids
def update(self, spec, document, upsert=False, manipulate=False,
safe=None, multi=False, check_keys=True, **kwargs):
multi=False, check_keys=True, **kwargs):
"""Update a document(s) in this collection.
Raises :class:`TypeError` if either `spec` or `document` is
@ -464,7 +464,6 @@ class Collection(common.BaseObject):
:class:`~pymongo.errors.InvalidName`. Only applies to
document replacement, not modification through $
operators.
- `safe` (optional): **DEPRECATED** - Use `w` instead.
- `multi` (optional): update all documents that match
`spec`, rather than just the first matching document. The
default value for `multi` is currently ``False``, but this
@ -491,6 +490,8 @@ class Collection(common.BaseObject):
- A document (dict) describing the effect of the update or ``None``
if write acknowledgement is disabled.
.. versionchanged:: 3.0
Removed the `safe` parameter
.. versionadded:: 1.8
Support for passing `getLastError` options as keyword
arguments.
@ -517,7 +518,7 @@ class Collection(common.BaseObject):
if manipulate:
document = self.__database._fix_incoming(document, self)
safe, options = self._get_write_mode(safe, **kwargs)
safe, options = self._get_write_mode(kwargs)
if document:
# If a top level key begins with '$' this is a modify operation
@ -571,7 +572,7 @@ class Collection(common.BaseObject):
"""
self.__database.drop_collection(self.__name)
def remove(self, spec_or_id=None, safe=None, multi=True, **kwargs):
def remove(self, spec_or_id=None, multi=True, **kwargs):
"""Remove a document(s) from this collection.
.. warning:: Calls to :meth:`remove` should be performed with
@ -596,7 +597,6 @@ class Collection(common.BaseObject):
- `spec_or_id` (optional): a dictionary specifying the
documents to be removed OR any other type specifying the
value of ``"_id"`` for the document to be removed
- `safe` (optional): **DEPRECATED** - Use `w` instead.
- `multi` (optional): If ``True`` (the default) remove all documents
matching `spec_or_id`, otherwise remove only the first matching
document.
@ -620,6 +620,8 @@ class Collection(common.BaseObject):
- A document (dict) describing the effect of the remove or ``None``
if write acknowledgement is disabled.
.. versionchanged:: 3.0
Removed the `safe` parameter
.. versionadded:: 1.8
Support for passing `getLastError` options as keyword arguments.
.. versionchanged:: 1.7 Accept any type other than a ``dict``
@ -641,7 +643,7 @@ class Collection(common.BaseObject):
if not isinstance(spec_or_id, dict):
spec_or_id = {"_id": spec_or_id}
safe, options = self._get_write_mode(safe, **kwargs)
safe, options = self._get_write_mode(kwargs)
client = self.database.connection

View File

@ -252,7 +252,6 @@ def validate_uuid_subtype(dummy, value):
# readpreferencetags is an alias for tag_sets.
VALIDATORS = {
'replicaset': validate_basestring,
'safe': validate_boolean,
'w': validate_int_or_basestring,
'wtimeout': validate_integer,
'wtimeoutms': validate_integer,
@ -305,7 +304,7 @@ def validate(option, value):
return lower, value
SAFE_OPTIONS = frozenset([
WRITE_CONCERN_OPTIONS = frozenset([
'w',
'wtimeout',
'wtimeoutms',
@ -324,7 +323,7 @@ class WriteConcern(dict):
super(WriteConcern, self).__init__(*args, **kwargs)
def __setitem__(self, key, value):
if key not in SAFE_OPTIONS:
if key not in WRITE_CONCERN_OPTIONS:
raise ConfigurationError("%s is not a valid write "
"concern option." % (key,))
key, value = validate(key, value)
@ -343,7 +342,6 @@ class BaseObject(object):
self.__read_pref = ReadPreference.PRIMARY
self.__tag_sets = [{}]
self.__secondary_acceptable_latency_ms = 15
self.__safe = None
self.__uuid_subtype = OLD_UUID_SUBTYPE
self.__write_concern = WriteConcern()
self.__set_options(options)
@ -352,22 +350,7 @@ class BaseObject(object):
raise ConfigurationError(
"ReadPreference PRIMARY cannot be combined with tags")
# If safe hasn't been implicitly set by write concerns then set it.
if self.__safe is None:
if options.get("w") == 0:
self.__safe = False
else:
self.__safe = validate_boolean('safe',
options.get("safe", True))
# Always do the most "safe" thing, but warn about conflicts.
if self.__safe and options.get('w') == 0:
warnings.warn("Conflicting write concerns: %s. Write concern "
"options were configured, but w=0 disables all "
"other options." % self.write_concern,
UserWarning)
def __set_safe_option(self, option, value):
def __set_write_concern_option(self, option, value):
"""Validates and sets getlasterror options for this
object (MongoClient, Database, Collection, etc.)
"""
@ -375,8 +358,6 @@ class BaseObject(object):
self.__write_concern.pop(option, None)
else:
self.__write_concern[option] = value
if option != "w" or value != 0:
self.__safe = True
def __set_options(self, options):
"""Validates and sets all options passed to this object."""
@ -393,13 +374,13 @@ class BaseObject(object):
):
self.__secondary_acceptable_latency_ms = \
validate_positive_float(option, value)
elif option in SAFE_OPTIONS:
elif option in WRITE_CONCERN_OPTIONS:
if option == 'journal':
self.__set_safe_option('j', value)
self.__set_write_concern_option('j', value)
elif option == 'wtimeoutms':
self.__set_safe_option('wtimeout', value)
self.__set_write_concern_option('wtimeout', value)
else:
self.__set_safe_option(option, value)
self.__set_write_concern_option(option, value)
def __set_write_concern(self, value):
"""Property setter for write_concern."""
@ -546,24 +527,6 @@ class BaseObject(object):
uuid_subtype = property(__get_uuid_subtype, __set_uuid_subtype)
def __get_safe(self):
"""**DEPRECATED:** Use the 'w' :attr:`write_concern` option instead.
Use getlasterror with every write operation?
.. versionadded:: 2.0
"""
return self.__safe
def __set_safe(self, value):
"""Property setter for safe"""
warnings.warn("safe is deprecated. Please use the"
" 'w' write_concern option instead.",
DeprecationWarning, stacklevel=2)
self.__safe = validate_boolean('safe', value)
safe = property(__get_safe, __set_safe)
def get_lasterror_options(self):
"""DEPRECATED: Use :attr:`write_concern` instead.
@ -584,7 +547,7 @@ class BaseObject(object):
Set getlasterror options for this instance.
Valid options include j=<bool>, w=<int/string>, wtimeout=<int>,
and fsync=<bool>. Implies safe=True.
and fsync=<bool>.
:Parameters:
- `**kwargs`: Options should be passed as keyword
@ -598,7 +561,7 @@ class BaseObject(object):
"write_concern instead.", DeprecationWarning,
stacklevel=2)
for key, value in kwargs.iteritems():
self.__set_safe_option(key, value)
self.__set_write_concern_option(key, value)
def unset_lasterror_options(self, *options):
"""DEPRECATED: Use :attr:`write_concern` instead.
@ -606,7 +569,6 @@ class BaseObject(object):
Unset getlasterror options for this instance.
If no options are passed unsets all getlasterror options.
This does not set `safe` to False.
:Parameters:
- `*options`: The list of options to unset.
@ -631,55 +593,22 @@ class BaseObject(object):
We don't want to override user write concern options if write concern
is already enabled.
"""
if self.safe and self.__write_concern.get('w') != 0:
if self.__write_concern.get('w') != 0:
return {}
return {'w': 1}
def _get_write_mode(self, safe=None, **options):
def _get_write_mode(self, options):
"""Get the current write mode.
Determines if the current write is safe or not based on the
passed in or inherited safe value, write_concern values, or
passed options.
Determines if the current write is acknowledged or not based on the
inherited write_concern values, or passed options.
:Parameters:
- `safe`: check that the operation succeeded?
- `**options`: overriding write concern options.
- `options`: overriding write concern options.
.. versionadded:: 2.3
"""
# Don't ever send w=1 to the server.
def pop1(dct):
if dct.get('w') == 1:
dct.pop('w')
return dct
if safe is not None:
warnings.warn("The safe parameter is deprecated. Please use "
"write concern options instead.", DeprecationWarning,
stacklevel=3)
validate_boolean('safe', safe)
# Passed options override collection level defaults.
if safe is not None or options:
if safe or options:
if not options:
options = self.__write_concern.copy()
# Backwards compatability edge case. Call getLastError
# with no options if safe=True was passed but collection
# level defaults have been disabled with w=0.
# These should be equivalent:
if options.get('w') == 0:
return True, {}
# Passing w=0 overrides passing safe=True.
return options.get('w') != 0, pop1(options)
write_concern = options or self.__write_concern
if write_concern.get('w') == 0:
return False, {}
# Fall back to collection level defaults.
# w=0 takes precedence over self.safe = True
if self.__write_concern.get('w') == 0:
return False, {}
elif self.safe or self.__write_concern.get('w', 0) != 0:
return True, pop1(self.__write_concern.copy())
return False, {}
return True, write_concern

View File

@ -64,7 +64,6 @@ class Database(common.BaseObject):
tag_sets=connection.tag_sets,
secondary_acceptable_latency_ms=(
connection.secondary_acceptable_latency_ms),
safe=connection.safe,
uuidrepresentation=connection.uuid_subtype,
**connection.write_concern)

View File

@ -69,7 +69,6 @@ class MasterSlaveConnection(BaseObject):
super(MasterSlaveConnection,
self).__init__(read_preference=ReadPreference.SECONDARY,
safe=master.safe,
**master.write_concern)
self.__master = master
@ -211,7 +210,6 @@ class MasterSlaveConnection(BaseObject):
:Parameters:
- `operation`: opcode of the message
- `data`: data to send
- `safe`: perform a getLastError after sending the message
"""
if _connection_to_use is None or _connection_to_use == -1:
return self.__master._send_message(message,

View File

@ -862,7 +862,7 @@ class TestReplicaSetAuth(HATestCase):
def test_auth_during_failover(self):
self.assertTrue(self.db.authenticate('user', 'userpass'))
self.assertTrue(self.db.foo.insert({'foo': 'bar'},
safe=True, w=3, wtimeout=3000))
w=3, wtimeout=3000))
self.db.logout()
self.assertRaises(OperationFailure, self.db.foo.find_one)

View File

@ -852,12 +852,6 @@ class TestCollection(unittest.TestCase):
lambda: db.test.insert([{'i': 2}] * 2, w=1),
)
# Misconfigured value for safe
self.assertRaises(
TypeError,
lambda: db.test.insert([{'i': 2}] * 2, safe=1),
)
def test_insert_iterables(self):
db = self.db
@ -979,10 +973,6 @@ 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)
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)

View File

@ -43,100 +43,59 @@ 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)
try:
self.assertRaises(UserWarning, lambda:
MongoClient(host, port, wtimeout=1000, w=0))
try:
MongoClient(host, port, wtimeout=1000, w=1)
except UserWarning:
self.fail()
try:
MongoClient(host, port, wtimeout=1000)
except UserWarning:
self.fail()
finally:
warnings.resetwarnings()
warnings.simplefilter("ignore")
# MongoClient test
c = MongoClient(pair)
self.assertTrue(c.safe)
self.assertEqual({}, c.get_lasterror_options())
db = c.pymongo_test
db.drop_collection("test")
self.assertTrue(db.safe)
self.assertEqual({}, db.get_lasterror_options())
coll = db.test
self.assertTrue(coll.safe)
self.assertEqual({}, coll.get_lasterror_options())
self.assertEqual((True, {}), coll._get_write_mode())
coll.safe = False
self.assertEqual((True, {}), coll._get_write_mode({}))
coll.write_concern.update(w=1)
self.assertEqual((True, {}), coll._get_write_mode())
self.assertEqual((True, {'w': 1}), coll._get_write_mode({}))
coll.write_concern.update(w=3)
self.assertEqual((True, {'w': 3}), coll._get_write_mode())
coll.safe = True
self.assertEqual((True, {'w': 3}), coll._get_write_mode({}))
coll.write_concern.update(w=0)
self.assertEqual((False, {}), coll._get_write_mode())
# Setting any safe operations overrides explicit safe
self.assertTrue(MongoClient(host, port, wtimeout=1000, safe=False).safe)
self.assertEqual((False, {}), coll._get_write_mode({}))
c = MongoClient(pair, w='majority',
wtimeout=300, fsync=True, j=True)
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.safe)
self.assertEqual(d, db.get_lasterror_options())
coll = db.test
self.assertTrue(coll.safe)
self.assertEqual(d, coll.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/?'
'w=1;wtimeout=300;'
'fsync=true;j=true' % (pair,))
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.safe)
self.assertEqual(d, db.get_lasterror_options())
self.assertEqual(d, db.write_concern)
coll = db.test
self.assertTrue(coll.safe)
self.assertEqual(d, coll.get_lasterror_options())
self.assertEqual(d, coll.write_concern)
cursor = coll.find()
c.unset_lasterror_options()
self.assertTrue(c.safe)
c.safe = False
self.assertFalse(c.safe)
self.assertEqual({}, c.get_lasterror_options())
self.assertEqual({}, c.write_concern)
db = c.pymongo_test
self.assertFalse(db.safe)
self.assertEqual({}, db.get_lasterror_options())
self.assertEqual({}, db.write_concern)
coll = db.test
self.assertFalse(coll.safe)
self.assertEqual({}, coll.get_lasterror_options())
self.assertEqual({}, coll.write_concern)
@ -145,10 +104,8 @@ class TestCommon(unittest.TestCase):
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())
@ -157,10 +114,8 @@ class TestCommon(unittest.TestCase):
self.assertEqual({'w': 'majority'}, db.write_concern)
self.assertEqual({}, c.get_lasterror_options())
self.assertEqual({}, c.write_concern)
self.assertFalse(c.safe)
self.assertRaises(ConfigurationError, coll.set_lasterror_options, foo=20)
self.assertRaises(TypeError, coll._BaseObject__set_safe, 20)
coll.remove()
coll.unset_lasterror_options()
@ -365,26 +320,20 @@ class TestCommon(unittest.TestCase):
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)
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))
@ -404,26 +353,20 @@ class TestCommon(unittest.TestCase):
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)
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))

View File

@ -413,16 +413,13 @@ class TestMasterSlaveConnection(unittest.TestCase, TestRequestMixin):
def test_base_object(self):
c = self.client
self.assertTrue(bool(c.read_preference))
self.assertTrue(c.safe)
self.assertEqual({}, c.get_lasterror_options())
db = c.pymongo_test
self.assertTrue(bool(c.read_preference))
self.assertTrue(db.safe)
self.assertEqual({}, db.get_lasterror_options())
coll = db.test
coll.drop()
self.assertTrue(bool(c.read_preference))
self.assertTrue(coll.safe)
self.assertEqual({}, coll.get_lasterror_options())
cursor = coll.find()
self.assertTrue(bool(cursor._Cursor__read_preference))
@ -431,15 +428,12 @@ class TestMasterSlaveConnection(unittest.TestCase, TestRequestMixin):
wtimeout=10000 # Wait 10 seconds for replication to complete
c.set_lasterror_options(w=w, wtimeout=wtimeout)
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.assertTrue(bool(c.read_preference))
self.assertTrue(db.safe)
self.assertEqual({'w': w, 'wtimeout': wtimeout}, db.get_lasterror_options())
coll = db.test
self.assertTrue(bool(c.read_preference))
self.assertTrue(coll.safe)
self.assertEqual({'w': w, 'wtimeout': wtimeout},
coll.get_lasterror_options())
cursor = coll.find()
@ -451,10 +445,8 @@ class TestMasterSlaveConnection(unittest.TestCase, TestRequestMixin):
coll.remove({'foo': 'bar'})
self.assertEqual(0, coll.find({'foo': 'bar'}).count())
c.safe = False
c.unset_lasterror_options()
self.assertTrue(bool(self.client.read_preference))
self.assertFalse(self.client.safe)
self.assertEqual({}, self.client.get_lasterror_options())
def test_document_class(self):

View File

@ -269,7 +269,6 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin):
self.assertEqual(obj.read_preference, ReadPreference.SECONDARY)
self.assertEqual(obj.tag_sets, tag_sets)
self.assertEqual(obj.secondary_acceptable_latency_ms, 77)
self.assertEqual(obj.safe, True)
cursor = c.pymongo_test.test.find()
self.assertEqual(