Skip to content

Commit bc6368d

Browse files
committed
Fixing write concern logic on a collection - PYTHON-474
Adding warnings in documentation about a change in side effects when calling write_concern
1 parent ce0345d commit bc6368d

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

pymongo/common.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,14 @@ def __get_write_concern(self):
388388
389389
.. note:: Accessing :attr:`write_concern` returns its value
390390
(a subclass of :class:`dict`), not a copy.
391+
392+
.. warning:: If you are using :class:`~pymongo.connection.Connection`
393+
or :class:`~pymongo.replica_set_connection.ReplicaSetConnection`
394+
make sure you explicitly set ``w`` to 1 (or a greater value) or
395+
:attr:`safe` to ``True``. Unlike calling
396+
:meth:`set_lasterror_options`, setting an option in
397+
:attr:`write_concern` does not implicitly set :attr:`safe`
398+
to ``True``.
391399
"""
392400
# To support dict style access we have to return the actual
393401
# WriteConcern here, not a copy.
@@ -603,7 +611,9 @@ def pop1(dct):
603611

604612
# Fall back to collection level defaults.
605613
# w=0 takes precedence over self.safe = True
606-
if self.safe and self.__write_concern.get('w') != 0:
614+
if self.__write_concern.get('w') == 0:
615+
return False, {}
616+
elif self.safe or self.__write_concern.get('w', 0) != 0:
607617
return True, pop1(self.__write_concern.copy())
608618

609619
return False, {}

test/test_common.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
from bson.objectid import ObjectId
2727
from bson.son import SON
28+
from pymongo.connection import Connection
2829
from pymongo.mongo_client import MongoClient
2930
from pymongo.mongo_replica_set_client import MongoReplicaSetClient
3031
from pymongo.errors import ConfigurationError, OperationFailure
@@ -56,6 +57,39 @@ def test_baseobject(self):
5657

5758
warnings.simplefilter("ignore")
5859

60+
# Connection tests
61+
c = Connection(pair)
62+
self.assertFalse(c.slave_okay)
63+
self.assertFalse(c.safe)
64+
self.assertEqual({}, c.get_lasterror_options())
65+
db = c.pymongo_test
66+
db.drop_collection("test")
67+
self.assertFalse(db.slave_okay)
68+
self.assertFalse(db.safe)
69+
self.assertEqual({}, db.get_lasterror_options())
70+
coll = db.test
71+
self.assertFalse(coll.slave_okay)
72+
self.assertFalse(coll.safe)
73+
self.assertEqual({}, coll.get_lasterror_options())
74+
75+
self.assertEqual((False, {}), coll._get_write_mode())
76+
coll.safe = False
77+
coll.write_concern.update(w=1)
78+
self.assertEqual((True, {}), coll._get_write_mode())
79+
coll.write_concern.update(w=3)
80+
self.assertEqual((True, {'w': 3}), coll._get_write_mode())
81+
82+
coll.safe = True
83+
coll.write_concern.update(w=0)
84+
self.assertEqual((False, {}), coll._get_write_mode())
85+
86+
coll = db.test
87+
cursor = coll.find()
88+
self.assertFalse(cursor._Cursor__slave_okay)
89+
cursor = coll.find(slave_okay=True)
90+
self.assertTrue(cursor._Cursor__slave_okay)
91+
92+
# MongoClient test
5993
c = MongoClient(pair)
6094
self.assertFalse(c.slave_okay)
6195
self.assertTrue(c.safe)
@@ -69,6 +103,19 @@ def test_baseobject(self):
69103
self.assertFalse(coll.slave_okay)
70104
self.assertTrue(coll.safe)
71105
self.assertEqual({}, coll.get_lasterror_options())
106+
107+
self.assertEqual((True, {}), coll._get_write_mode())
108+
coll.safe = False
109+
coll.write_concern.update(w=1)
110+
self.assertEqual((True, {}), coll._get_write_mode())
111+
coll.write_concern.update(w=3)
112+
self.assertEqual((True, {'w': 3}), coll._get_write_mode())
113+
114+
coll.safe = True
115+
coll.write_concern.update(w=0)
116+
self.assertEqual((False, {}), coll._get_write_mode())
117+
118+
coll = db.test
72119
cursor = coll.find()
73120
self.assertFalse(cursor._Cursor__slave_okay)
74121
cursor = coll.find(slave_okay=True)

0 commit comments

Comments
 (0)