123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- # Copyright 2009-present MongoDB, Inc.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- """Exceptions raised by PyMongo."""
- import sys
- from bson.errors import *
- try:
- # CPython 3.7+
- from ssl import SSLCertVerificationError as CertificateError
- except ImportError:
- try:
- from ssl import CertificateError
- except ImportError:
- class CertificateError(ValueError):
- pass
- class PyMongoError(Exception):
- """Base class for all PyMongo exceptions."""
- def __init__(self, message='', error_labels=None):
- super(PyMongoError, self).__init__(message)
- self._message = message
- self._error_labels = set(error_labels or [])
- def has_error_label(self, label):
- """Return True if this error contains the given label.
- .. versionadded:: 3.7
- """
- return label in self._error_labels
- def _add_error_label(self, label):
- """Add the given label to this error."""
- self._error_labels.add(label)
- def _remove_error_label(self, label):
- """Remove the given label from this error."""
- self._error_labels.discard(label)
- if sys.version_info[0] == 2:
- def __str__(self):
- if isinstance(self._message, unicode):
- return self._message.encode('utf-8', errors='replace')
- return str(self._message)
- def __unicode__(self):
- if isinstance(self._message, unicode):
- return self._message
- return unicode(self._message, 'utf-8', errors='replace')
- class ProtocolError(PyMongoError):
- """Raised for failures related to the wire protocol."""
- class ConnectionFailure(PyMongoError):
- """Raised when a connection to the database cannot be made or is lost."""
- class AutoReconnect(ConnectionFailure):
- """Raised when a connection to the database is lost and an attempt to
- auto-reconnect will be made.
- In order to auto-reconnect you must handle this exception, recognizing that
- the operation which caused it has not necessarily succeeded. Future
- operations will attempt to open a new connection to the database (and
- will continue to raise this exception until the first successful
- connection is made).
- Subclass of :exc:`~pymongo.errors.ConnectionFailure`.
- """
- def __init__(self, message='', errors=None):
- error_labels = None
- if errors is not None and isinstance(errors, dict):
- error_labels = errors.get('errorLabels')
- super(AutoReconnect, self).__init__(message, error_labels)
- self.errors = self.details = errors or []
- class NetworkTimeout(AutoReconnect):
- """An operation on an open connection exceeded socketTimeoutMS.
- The remaining connections in the pool stay open. In the case of a write
- operation, you cannot know whether it succeeded or failed.
- Subclass of :exc:`~pymongo.errors.AutoReconnect`.
- """
- def _format_detailed_error(message, details):
- if details is not None:
- message = "%s, full error: %s" % (message, details)
- if sys.version_info[0] == 2 and isinstance(message, unicode):
- message = message.encode('utf-8', errors='replace')
- return message
- class NotMasterError(AutoReconnect):
- """**DEPRECATED** - The server responded "not master" or
- "node is recovering".
- This exception has been deprecated and will be removed in PyMongo 4.0.
- Use :exc:`~pymongo.errors.NotPrimaryError` instead.
- .. versionchanged:: 3.12
- Deprecated. Use :exc:`~pymongo.errors.NotPrimaryError` instead.
- """
- def __init__(self, message='', errors=None):
- super(NotMasterError, self).__init__(
- _format_detailed_error(message, errors), errors=errors)
- class NotPrimaryError(NotMasterError):
- """The server responded "not primary" or "node is recovering".
- These errors result from a query, write, or command. The operation failed
- because the client thought it was using the primary but the primary has
- stepped down, or the client thought it was using a healthy secondary but
- the secondary is stale and trying to recover.
- The client launches a refresh operation on a background thread, to update
- its view of the server as soon as possible after throwing this exception.
- Subclass of :exc:`~pymongo.errors.AutoReconnect`.
- .. versionadded:: 3.12
- """
- def __init__(self, message='', errors=None):
- super(NotPrimaryError, self).__init__(message, errors=errors)
- class ServerSelectionTimeoutError(AutoReconnect):
- """Thrown when no MongoDB server is available for an operation
- If there is no suitable server for an operation PyMongo tries for
- ``serverSelectionTimeoutMS`` (default 30 seconds) to find one, then
- throws this exception. For example, it is thrown after attempting an
- operation when PyMongo cannot connect to any server, or if you attempt
- an insert into a replica set that has no primary and does not elect one
- within the timeout window, or if you attempt to query with a Read
- Preference that the replica set cannot satisfy.
- """
- class ConfigurationError(PyMongoError):
- """Raised when something is incorrectly configured.
- """
- class OperationFailure(PyMongoError):
- """Raised when a database operation fails.
- .. versionadded:: 2.7
- The :attr:`details` attribute.
- """
- def __init__(self, error, code=None, details=None, max_wire_version=None):
- error_labels = None
- if details is not None:
- error_labels = details.get('errorLabels')
- super(OperationFailure, self).__init__(
- _format_detailed_error(error, details), error_labels=error_labels)
- self.__code = code
- self.__details = details
- self.__max_wire_version = max_wire_version
- @property
- def _max_wire_version(self):
- return self.__max_wire_version
- @property
- def code(self):
- """The error code returned by the server, if any.
- """
- return self.__code
- @property
- def details(self):
- """The complete error document returned by the server.
- Depending on the error that occurred, the error document
- may include useful information beyond just the error
- message. When connected to a mongos the error document
- may contain one or more subdocuments if errors occurred
- on multiple shards.
- """
- return self.__details
- class CursorNotFound(OperationFailure):
- """Raised while iterating query results if the cursor is
- invalidated on the server.
- .. versionadded:: 2.7
- """
- class ExecutionTimeout(OperationFailure):
- """Raised when a database operation times out, exceeding the $maxTimeMS
- set in the query or command option.
- .. note:: Requires server version **>= 2.6.0**
- .. versionadded:: 2.7
- """
- class WriteConcernError(OperationFailure):
- """Base exception type for errors raised due to write concern.
- .. versionadded:: 3.0
- """
- class WriteError(OperationFailure):
- """Base exception type for errors raised during write operations.
- .. versionadded:: 3.0
- """
- class WTimeoutError(WriteConcernError):
- """Raised when a database operation times out (i.e. wtimeout expires)
- before replication completes.
- With newer versions of MongoDB the `details` attribute may include
- write concern fields like 'n', 'updatedExisting', or 'writtenTo'.
- .. versionadded:: 2.7
- """
- class DuplicateKeyError(WriteError):
- """Raised when an insert or update fails due to a duplicate key error."""
- class BulkWriteError(OperationFailure):
- """Exception class for bulk write errors.
- .. versionadded:: 2.7
- """
- def __init__(self, results):
- super(BulkWriteError, self).__init__(
- "batch op errors occurred", 65, results)
- def __reduce__(self):
- return self.__class__, (self.details,)
- class InvalidOperation(PyMongoError):
- """Raised when a client attempts to perform an invalid operation."""
- class InvalidName(PyMongoError):
- """Raised when an invalid name is used."""
- class CollectionInvalid(PyMongoError):
- """Raised when collection validation fails."""
- class InvalidURI(ConfigurationError):
- """Raised when trying to parse an invalid mongodb URI."""
- class ExceededMaxWaiters(PyMongoError):
- """Raised when a thread tries to get a connection from a pool and
- ``maxPoolSize * waitQueueMultiple`` threads are already waiting.
- .. versionadded:: 2.6
- """
- pass
- class DocumentTooLarge(InvalidDocument):
- """Raised when an encoded document is too large for the connected server.
- """
- pass
- class EncryptionError(PyMongoError):
- """Raised when encryption or decryption fails.
- This error always wraps another exception which can be retrieved via the
- :attr:`cause` property.
- .. versionadded:: 3.9
- """
- def __init__(self, cause):
- super(EncryptionError, self).__init__(str(cause))
- self.__cause = cause
- @property
- def cause(self):
- """The exception that caused this encryption or decryption error."""
- return self.__cause
- class _OperationCancelled(AutoReconnect):
- """Internal error raised when a socket operation is cancelled.
- """
- pass
|