Skip to content

Commit 9d75726

Browse files
PYTHON-2572 Introduce NotPrimaryError and deprecate NotMasterError (#646)
(cherry picked from commit ff6ca53)
1 parent ccb62d4 commit 9d75726

17 files changed

+89
-65
lines changed

doc/changelog.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ Deprecations
4141
and :meth:`~pymongo.database.Database.profiling_info`. Instead, users
4242
should run the `profile command`_ with the
4343
:meth:`~pymongo.database.Database.command` helper directly.
44+
- Deprecated :exc:`~pymongo.errors.NotMasterError`. Users should
45+
use :exc:`~pymongo.errors.NotPrimaryError` instead.
4446

4547
.. _PYTHON-2466: https://jira.mongodb.org/browse/PYTHON-2466
4648
.. _PYTHON-1690: https://jira.mongodb.org/browse/PYTHON-1690

pymongo/change_stream.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@
4141
189, # PrimarySteppedDown
4242
262, # ExceededTimeLimit
4343
9001, # SocketException
44-
10107, # NotMaster
44+
10107, # NotWritablePrimary
4545
11600, # InterruptedAtShutdown
4646
11602, # InterruptedDueToReplStateChange
47-
13435, # NotMasterNoSlaveOk
48-
13436, # NotMasterOrSecondary
47+
13435, # NotPrimaryNoSecondaryOk
48+
13436, # NotPrimaryOrSecondary
4949
63, # StaleShardVersion
5050
150, # StaleEpoch
5151
13388, # StaleConfig

pymongo/errors.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,22 @@ def _format_detailed_error(message, details):
109109

110110

111111
class NotMasterError(AutoReconnect):
112-
"""The server responded "not master" or "node is recovering".
112+
"""**DEPRECATED** - The server responded "not master" or
113+
"node is recovering".
114+
115+
This exception has been deprecated and will be removed in PyMongo 4.0.
116+
Use :exc:`~pymongo.errors.NotPrimaryError` instead.
117+
118+
.. versionchanged:: 3.12
119+
Deprecated. Use :exc:`~pymongo.errors.NotPrimaryError` instead.
120+
"""
121+
def __init__(self, message='', errors=None):
122+
super(NotMasterError, self).__init__(
123+
_format_detailed_error(message, errors), errors=errors)
124+
125+
126+
class NotPrimaryError(NotMasterError):
127+
"""The server responded "not primary" or "node is recovering".
113128
114129
These errors result from a query, write, or command. The operation failed
115130
because the client thought it was using the primary but the primary has
@@ -120,10 +135,11 @@ class NotMasterError(AutoReconnect):
120135
its view of the server as soon as possible after throwing this exception.
121136
122137
Subclass of :exc:`~pymongo.errors.AutoReconnect`.
138+
139+
.. versionadded:: 3.12
123140
"""
124141
def __init__(self, message='', errors=None):
125-
super(NotMasterError, self).__init__(
126-
_format_detailed_error(message, errors), errors=errors)
142+
super(NotPrimaryError, self).__init__(message, errors=errors)
127143

128144

129145
class ServerSelectionTimeoutError(AutoReconnect):

pymongo/helpers.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from pymongo.errors import (CursorNotFound,
2424
DuplicateKeyError,
2525
ExecutionTimeout,
26-
NotMasterError,
26+
NotPrimaryError,
2727
OperationFailure,
2828
WriteError,
2929
WriteConcernError,
@@ -34,15 +34,15 @@
3434
11600, # InterruptedAtShutdown
3535
91, # ShutdownInProgress
3636
])
37-
# From the SDAM spec, the "not master" error codes are combined with the
37+
# From the SDAM spec, the "not primary" error codes are combined with the
3838
# "node is recovering" error codes (of which the "node is shutting down"
3939
# errors are a subset).
4040
_NOT_MASTER_CODES = frozenset([
41-
10058, # LegacyNotPrimary <=3.2 "not master" error code
42-
10107, # NotMaster
43-
13435, # NotMasterNoSlaveOk
41+
10058, # LegacyNotPrimary <=3.2 "not primary" error code
42+
10107, # NotWritablePrimary
43+
13435, # NotPrimaryNoSecondaryOk
4444
11602, # InterruptedDueToReplStateChange
45-
13436, # NotMasterOrSecondary
45+
13436, # NotPrimaryOrSecondary
4646
189, # PrimarySteppedDown
4747
]) | _SHUTDOWN_CODES
4848
# From the retryable writes spec.
@@ -147,12 +147,12 @@ def _check_command_response(response, max_wire_version,
147147
elif errmsg in allowable_errors:
148148
return
149149

150-
# Server is "not master" or "recovering"
150+
# Server is "not primary" or "recovering"
151151
if code is not None:
152152
if code in _NOT_MASTER_CODES:
153-
raise NotMasterError(errmsg, response)
153+
raise NotPrimaryError(errmsg, response)
154154
elif "not master" in errmsg or "node is recovering" in errmsg:
155-
raise NotMasterError(errmsg, response)
155+
raise NotPrimaryError(errmsg, response)
156156

157157
# Other errors
158158
# findAndModify with upsert can raise duplicate key error
@@ -184,7 +184,7 @@ def _check_gle_response(result, max_wire_version):
184184
return result
185185

186186
if error_msg.startswith("not master"):
187-
raise NotMasterError(error_msg, result)
187+
raise NotPrimaryError(error_msg, result)
188188

189189
details = result
190190

pymongo/message.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
DocumentTooLarge,
4848
ExecutionTimeout,
4949
InvalidOperation,
50-
NotMasterError,
50+
NotPrimaryError,
5151
OperationFailure,
5252
ProtocolError)
5353
from pymongo.read_concern import DEFAULT_READ_CONCERN
@@ -997,7 +997,7 @@ def legacy_write(self, request_id, msg, max_doc_size, acknowledged, docs):
997997
if isinstance(exc, OperationFailure):
998998
failure = _convert_write_result(
999999
self.name, cmd, exc.details)
1000-
elif isinstance(exc, NotMasterError):
1000+
elif isinstance(exc, NotPrimaryError):
10011001
failure = exc.details
10021002
else:
10031003
failure = _convert_exception(exc)
@@ -1022,7 +1022,7 @@ def write_command(self, request_id, msg, docs):
10221022
except Exception as exc:
10231023
if self.publish:
10241024
duration = (datetime.datetime.now() - start) + duration
1025-
if isinstance(exc, (NotMasterError, OperationFailure)):
1025+
if isinstance(exc, (NotPrimaryError, OperationFailure)):
10261026
failure = exc.details
10271027
else:
10281028
failure = _convert_exception(exc)
@@ -1516,7 +1516,7 @@ def raw_response(self, cursor_id=None, user_fields=None):
15161516
15171517
Check the response for errors and unpack.
15181518
1519-
Can raise CursorNotFound, NotMasterError, ExecutionTimeout, or
1519+
Can raise CursorNotFound, NotPrimaryError, ExecutionTimeout, or
15201520
OperationFailure.
15211521
15221522
:Parameters:
@@ -1539,7 +1539,7 @@ def raw_response(self, cursor_id=None, user_fields=None):
15391539
# Fake the ok field if it doesn't exist.
15401540
error_object.setdefault("ok", 0)
15411541
if error_object["$err"].startswith("not master"):
1542-
raise NotMasterError(error_object["$err"], error_object)
1542+
raise NotPrimaryError(error_object["$err"], error_object)
15431543
elif error_object.get("code") == 50:
15441544
raise ExecutionTimeout(error_object.get("$err"),
15451545
error_object.get("code"),
@@ -1560,7 +1560,7 @@ def unpack_response(self, cursor_id=None,
15601560
Check the response for errors and unpack, returning a dictionary
15611561
containing the response data.
15621562
1563-
Can raise CursorNotFound, NotMasterError, ExecutionTimeout, or
1563+
Can raise CursorNotFound, NotPrimaryError, ExecutionTimeout, or
15641564
OperationFailure.
15651565
15661566
:Parameters:
@@ -1721,7 +1721,7 @@ def _first_batch(sock_info, db, coll, query, ntoreturn,
17211721
except Exception as exc:
17221722
if publish:
17231723
duration = (datetime.datetime.now() - start) + encoding_duration
1724-
if isinstance(exc, (NotMasterError, OperationFailure)):
1724+
if isinstance(exc, (NotPrimaryError, OperationFailure)):
17251725
failure = exc.details
17261726
else:
17271727
failure = _convert_exception(exc)

pymongo/mongo_client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
ConfigurationError,
6060
ConnectionFailure,
6161
InvalidOperation,
62-
NotMasterError,
62+
NotPrimaryError,
6363
OperationFailure,
6464
PyMongoError,
6565
ServerSelectionTimeoutError)
@@ -2289,7 +2289,7 @@ def _retryable_error_doc(exc):
22892289
wces = exc.details['writeConcernErrors']
22902290
wce = wces[-1] if wces else None
22912291
return wce
2292-
if isinstance(exc, (NotMasterError, OperationFailure)):
2292+
if isinstance(exc, (NotPrimaryError, OperationFailure)):
22932293
return exc.details
22942294
return None
22952295

@@ -2314,10 +2314,10 @@ def _add_retryable_write_error(exc, max_wire_version):
23142314
if code in helpers._RETRYABLE_ERROR_CODES:
23152315
exc._add_error_label("RetryableWriteError")
23162316

2317-
# Connection errors are always retryable except NotMasterError which is
2317+
# Connection errors are always retryable except NotPrimaryError which is
23182318
# handled above.
23192319
if (isinstance(exc, ConnectionFailure) and
2320-
not isinstance(exc, NotMasterError)):
2320+
not isinstance(exc, NotPrimaryError)):
23212321
exc._add_error_label("RetryableWriteError")
23222322

23232323

pymongo/monitor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from bson.py3compat import PY3
2222

2323
from pymongo import common, periodic_executor
24-
from pymongo.errors import (NotMasterError,
24+
from pymongo.errors import (NotPrimaryError,
2525
OperationFailure,
2626
_OperationCancelled)
2727
from pymongo.ismaster import IsMaster
@@ -215,7 +215,7 @@ def _check_server(self):
215215
try:
216216
try:
217217
return self._check_once()
218-
except (OperationFailure, NotMasterError) as exc:
218+
except (OperationFailure, NotPrimaryError) as exc:
219219
# Update max cluster time even when isMaster fails.
220220
self._topology.receive_cluster_time(
221221
exc.details.get('$clusterTime'))

pymongo/network.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
from pymongo.common import MAX_MESSAGE_SIZE
2828
from pymongo.compression_support import decompress, _NO_COMPRESSION
2929
from pymongo.errors import (AutoReconnect,
30-
NotMasterError,
30+
NotPrimaryError,
3131
OperationFailure,
3232
ProtocolError,
3333
NetworkTimeout,
@@ -163,7 +163,7 @@ def command(sock_info, dbname, spec, slave_ok, is_mongos,
163163
except Exception as exc:
164164
if publish:
165165
duration = (datetime.datetime.now() - start) + encoding_duration
166-
if isinstance(exc, (NotMasterError, OperationFailure)):
166+
if isinstance(exc, (NotPrimaryError, OperationFailure)):
167167
failure = exc.details
168168
else:
169169
failure = message._convert_exception(exc)

pymongo/pool.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
InvalidOperation,
4949
DocumentTooLarge,
5050
NetworkTimeout,
51-
NotMasterError,
51+
NotPrimaryError,
5252
OperationFailure,
5353
PyMongoError)
5454
from pymongo.hello import HelloCompat
@@ -755,7 +755,7 @@ def command(self, dbname, spec, slave_ok=False,
755755
unacknowledged=unacknowledged,
756756
user_fields=user_fields,
757757
exhaust_allowed=exhaust_allowed)
758-
except (OperationFailure, NotMasterError):
758+
except (OperationFailure, NotPrimaryError):
759759
raise
760760
# Catch socket.error, KeyboardInterrupt, etc. and close ourselves.
761761
except BaseException as error:
@@ -789,13 +789,13 @@ def receive_message(self, request_id):
789789
self._raise_connection_failure(error)
790790

791791
def _raise_if_not_writable(self, unacknowledged):
792-
"""Raise NotMasterError on unacknowledged write if this socket is not
792+
"""Raise NotPrimaryError on unacknowledged write if this socket is not
793793
writable.
794794
"""
795795
if unacknowledged and not self.is_writable:
796-
# Write won't succeed, bail as if we'd received a not master error.
797-
raise NotMasterError("not master", {
798-
"ok": 0, "errmsg": "not master", "code": 10107})
796+
# Write won't succeed, bail as if we'd received a not primary error.
797+
raise NotPrimaryError("not primary", {
798+
"ok": 0, "errmsg": "not primary", "code": 10107})
799799

800800
def legacy_write(self, request_id, msg, max_doc_size, with_last_error):
801801
"""Send OP_INSERT, etc., optionally returning response as a dict.
@@ -830,7 +830,7 @@ def write_command(self, request_id, msg):
830830
reply = self.receive_message(request_id)
831831
result = reply.command_response()
832832

833-
# Raises NotMasterError or OperationFailure.
833+
# Raises NotPrimaryError or OperationFailure.
834834
helpers._check_command_response(result, self.max_wire_version)
835835
return result
836836

pymongo/server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
from bson import _decode_all_selective
2020

21-
from pymongo.errors import NotMasterError, OperationFailure
21+
from pymongo.errors import NotPrimaryError, OperationFailure
2222
from pymongo.helpers import _check_command_response
2323
from pymongo.message import _convert_exception, _OpMsg
2424
from pymongo.response import Response, PinnedResponse
@@ -130,7 +130,7 @@ def run_operation(self, sock_info, operation, set_slave_okay, listeners,
130130
except Exception as exc:
131131
if publish:
132132
duration = datetime.now() - start
133-
if isinstance(exc, (NotMasterError, OperationFailure)):
133+
if isinstance(exc, (NotPrimaryError, OperationFailure)):
134134
failure = exc.details
135135
else:
136136
failure = _convert_exception(exc)

0 commit comments

Comments
 (0)