Skip to content

Commit 99aefd6

Browse files
committed
PYTHON-1413 - Restrict when we add readConcern
1 parent 8c3c562 commit 99aefd6

File tree

4 files changed

+95
-30
lines changed

4 files changed

+95
-30
lines changed

pymongo/collection.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
_raise_last_error)
4444
from pymongo.message import _UNICODE_REPLACE_CODEC_OPTIONS
4545
from pymongo.operations import IndexModel
46-
from pymongo.read_concern import DEFAULT_READ_CONCERN
4746
from pymongo.read_preferences import ReadPreference
4847
from pymongo.results import (BulkWriteResult,
4948
DeleteResult,
@@ -196,7 +195,7 @@ def _socket_for_writes(self):
196195
def _command(self, sock_info, command, slave_ok=False,
197196
read_preference=None,
198197
codec_options=None, check=True, allowable_errors=None,
199-
read_concern=DEFAULT_READ_CONCERN,
198+
read_concern=None,
200199
write_concern=None,
201200
parse_write_concern_error=False,
202201
collation=None,
@@ -2073,7 +2072,7 @@ def _aggregate(self, pipeline, cursor_class, first_batch_size, session,
20732072
and not dollar_out):
20742073
read_concern = self.read_concern
20752074
else:
2076-
read_concern = DEFAULT_READ_CONCERN
2075+
read_concern = None
20772076

20782077
# Avoid auto-injecting a session: aggregate() passes a session,
20792078
# aggregate_raw_batches() passes none.

pymongo/network.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
OperationFailure,
4343
ProtocolError)
4444
from pymongo.message import _OpReply
45-
from pymongo.read_concern import DEFAULT_READ_CONCERN
4645

4746

4847
_UNPACK_HEADER = struct.Struct("<iiii").unpack
@@ -52,7 +51,7 @@ def command(sock, dbname, spec, slave_ok, is_mongos,
5251
read_preference, codec_options, session, client, check=True,
5352
allowable_errors=None, address=None,
5453
check_keys=False, listeners=None, max_bson_size=None,
55-
read_concern=DEFAULT_READ_CONCERN,
54+
read_concern=None,
5655
parse_write_concern_error=False,
5756
collation=None, retryable_write=False):
5857
"""Execute a command over the socket, or raise socket.error.
@@ -96,12 +95,13 @@ def command(sock, dbname, spec, slave_ok, is_mongos,
9695
orig = spec
9796
if is_mongos:
9897
spec = message._maybe_add_read_preference(spec, read_preference)
99-
if read_concern.level:
100-
spec['readConcern'] = read_concern.document
101-
if (session and session.options.causal_consistency
102-
and session.operation_time is not None):
103-
spec.setdefault(
104-
'readConcern', {})['afterClusterTime'] = session.operation_time
98+
if read_concern:
99+
if read_concern.level:
100+
spec['readConcern'] = read_concern.document
101+
if (session and session.options.causal_consistency
102+
and session.operation_time is not None):
103+
spec.setdefault(
104+
'readConcern', {})['afterClusterTime'] = session.operation_time
105105
if collation is not None:
106106
spec['collation'] = collation
107107

pymongo/pool.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ class SSLError(socket.error):
4747
from pymongo.network import (command,
4848
receive_message,
4949
SocketChecker)
50-
from pymongo.read_concern import DEFAULT_READ_CONCERN
5150
from pymongo.read_preferences import ReadPreference
5251
from pymongo.server_type import SERVER_TYPE
5352
# Always use our backport so we always have support for IP address matching
@@ -435,7 +434,7 @@ def command(self, dbname, spec, slave_ok=False,
435434
read_preference=ReadPreference.PRIMARY,
436435
codec_options=DEFAULT_CODEC_OPTIONS, check=True,
437436
allowable_errors=None, check_keys=False,
438-
read_concern=DEFAULT_READ_CONCERN,
437+
read_concern=None,
439438
write_concern=None,
440439
parse_write_concern_error=False,
441440
collation=None,
@@ -463,7 +462,8 @@ def command(self, dbname, spec, slave_ok=False,
463462
- `retryable_write`: True if this command is a retryable write.
464463
"""
465464
self.check_session_auth_matches(session)
466-
if self.max_wire_version < 4 and not read_concern.ok_for_legacy:
465+
if (read_concern and self.max_wire_version < 4
466+
and not read_concern.ok_for_legacy):
467467
raise ConfigurationError(
468468
'read concern level of %s is not valid '
469469
'with a max wire version of %d.'

test/test_session.py

Lines changed: 82 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -688,15 +688,6 @@ def _test_reads(self, op):
688688

689689
@client_context.require_no_standalone
690690
def test_reads(self):
691-
self._test_reads(
692-
lambda coll, session: list(
693-
coll.database.list_collections(session=session)))
694-
self._test_reads(
695-
lambda coll, session: coll.database.list_collection_names(
696-
session=session))
697-
self._test_reads(
698-
lambda coll, session: coll.database.command(
699-
'ismaster', session=session))
700691
self._test_reads(
701692
lambda coll, session: list(coll.aggregate([], session=session)))
702693
self._test_reads(
@@ -705,17 +696,11 @@ def test_reads(self):
705696
lambda coll, session: coll.find_one({}, session=session))
706697
self._test_reads(
707698
lambda coll, session: coll.count(session=session))
708-
self._test_reads(
709-
lambda coll, session: list(coll.list_indexes(session=session)))
710-
self._test_reads(
711-
lambda coll, session: coll.index_information(session=session))
712-
self._test_reads(
713-
lambda coll, session: coll.options(session=session))
714699
self._test_reads(
715700
lambda coll, session: coll.distinct('foo', session=session))
716701
self._test_reads(
717702
lambda coll, session: coll.map_reduce(
718-
'function() {}', 'function() {}', 'output', session=session))
703+
'function() {}', 'function() {}', 'inline', session=session))
719704
self._test_reads(
720705
lambda coll, session: coll.inline_map_reduce(
721706
'function() {}', 'function() {}', session=session))
@@ -793,6 +778,87 @@ def test_writes(self):
793778
self._test_writes(
794779
lambda coll, session: coll.reindex(session=session))
795780

781+
def _test_no_read_concern(self, op):
782+
coll = self.client.pymongo_test.test
783+
with self.client.start_session() as sess:
784+
coll.find_one({}, session=sess)
785+
operation_time = sess.operation_time
786+
self.assertIsNotNone(operation_time)
787+
self.listener.results.clear()
788+
op(coll, sess)
789+
rc = self.listener.results['started'][0].command.get(
790+
'readConcern')
791+
self.assertIsNone(rc)
792+
793+
@client_context.require_no_standalone
794+
def test_writes_do_not_include_read_concern(self):
795+
self._test_no_read_concern(
796+
lambda coll, session: coll.bulk_write(
797+
[InsertOne({})], session=session))
798+
self._test_no_read_concern(
799+
lambda coll, session: coll.insert_one({}, session=session))
800+
self._test_no_read_concern(
801+
lambda coll, session: coll.insert_many([{}], session=session))
802+
self._test_no_read_concern(
803+
lambda coll, session: coll.replace_one(
804+
{'_id': 1}, {'x': 1}, session=session))
805+
self._test_no_read_concern(
806+
lambda coll, session: coll.update_one(
807+
{}, {'$set': {'X': 1}}, session=session))
808+
self._test_no_read_concern(
809+
lambda coll, session: coll.update_many(
810+
{}, {'$set': {'x': 1}}, session=session))
811+
self._test_no_read_concern(
812+
lambda coll, session: coll.delete_one({}, session=session))
813+
self._test_no_read_concern(
814+
lambda coll, session: coll.delete_many({}, session=session))
815+
self._test_no_read_concern(
816+
lambda coll, session: coll.find_one_and_replace(
817+
{'x': 1}, {'y': 1}, session=session))
818+
self._test_no_read_concern(
819+
lambda coll, session: coll.find_one_and_update(
820+
{'y': 1}, {'$set': {'x': 1}}, session=session))
821+
self._test_no_read_concern(
822+
lambda coll, session: coll.find_one_and_delete(
823+
{'x': 1}, session=session))
824+
self._test_no_read_concern(
825+
lambda coll, session: coll.create_index("foo", session=session))
826+
self._test_no_read_concern(
827+
lambda coll, session: coll.create_indexes(
828+
[IndexModel([("bar", ASCENDING)])], session=session))
829+
self._test_no_read_concern(
830+
lambda coll, session: coll.drop_index("foo_1", session=session))
831+
self._test_no_read_concern(
832+
lambda coll, session: coll.drop_indexes(session=session))
833+
self._test_no_read_concern(
834+
lambda coll, session: coll.reindex(session=session))
835+
self._test_no_read_concern(
836+
lambda coll, session: list(
837+
coll.aggregate([{"$out": "aggout"}], session=session)))
838+
self._test_no_read_concern(
839+
lambda coll, session: coll.map_reduce(
840+
'function() {}', 'function() {}', 'mrout', session=session))
841+
842+
# It's not a write, but currentOp also doesn't support readConcern
843+
self._test_no_read_concern(
844+
lambda coll, session: coll.database.current_op(session=session))
845+
846+
@client_context.require_no_standalone
847+
def test_get_more_does_not_include_read_concern(self):
848+
coll = self.client.pymongo_test.test
849+
with self.client.start_session() as sess:
850+
coll.find_one({}, session=sess)
851+
operation_time = sess.operation_time
852+
self.assertIsNotNone(operation_time)
853+
coll.insert_many([{}, {}])
854+
cursor = coll.find({}).batch_size(1)
855+
next(cursor)
856+
self.listener.results.clear()
857+
list(cursor)
858+
started = self.listener.results['started'][0]
859+
self.assertEqual(started.command_name, 'getMore')
860+
self.assertIsNone(started.command.get('readConcern'))
861+
796862
def test_session_not_causal(self):
797863
with self.client.start_session(causal_consistency=False) as s:
798864
self.client.pymongo_test.test.insert_one({}, session=s)

0 commit comments

Comments
 (0)