PYTHON-5115 Type validation errors should include the invalid type name (#2085)
Co-authored-by: Iris Ho <iris.ho@mongodb.com>
This commit is contained in:
parent
c42f3d6421
commit
44d1d40d65
@ -1386,7 +1386,7 @@ def is_valid(bson: bytes) -> bool:
|
||||
:param bson: the data to be validated
|
||||
"""
|
||||
if not isinstance(bson, bytes):
|
||||
raise TypeError("BSON data must be an instance of a subclass of bytes")
|
||||
raise TypeError(f"BSON data must be an instance of a subclass of bytes, not {type(bson)}")
|
||||
|
||||
try:
|
||||
_bson_to_dict(bson, DEFAULT_CODEC_OPTIONS)
|
||||
|
||||
@ -290,7 +290,7 @@ class Binary(bytes):
|
||||
subtype: int = BINARY_SUBTYPE,
|
||||
) -> Binary:
|
||||
if not isinstance(subtype, int):
|
||||
raise TypeError("subtype must be an instance of int")
|
||||
raise TypeError(f"subtype must be an instance of int, not {type(subtype)}")
|
||||
if subtype >= 256 or subtype < 0:
|
||||
raise ValueError("subtype must be contained in [0, 256)")
|
||||
# Support any type that implements the buffer protocol.
|
||||
@ -321,7 +321,7 @@ class Binary(bytes):
|
||||
.. versionadded:: 3.11
|
||||
"""
|
||||
if not isinstance(uuid, UUID):
|
||||
raise TypeError("uuid must be an instance of uuid.UUID")
|
||||
raise TypeError(f"uuid must be an instance of uuid.UUID, not {type(uuid)}")
|
||||
|
||||
if uuid_representation not in ALL_UUID_REPRESENTATIONS:
|
||||
raise ValueError(
|
||||
@ -470,7 +470,7 @@ class Binary(bytes):
|
||||
"""
|
||||
|
||||
if self.subtype != VECTOR_SUBTYPE:
|
||||
raise ValueError(f"Cannot decode subtype {self.subtype} as a vector.")
|
||||
raise ValueError(f"Cannot decode subtype {self.subtype} as a vector")
|
||||
|
||||
position = 0
|
||||
dtype, padding = struct.unpack_from("<sB", self, position)
|
||||
|
||||
@ -56,7 +56,7 @@ class Code(str):
|
||||
**kwargs: Any,
|
||||
) -> Code:
|
||||
if not isinstance(code, str):
|
||||
raise TypeError("code must be an instance of str")
|
||||
raise TypeError(f"code must be an instance of str, not {type(code)}")
|
||||
|
||||
self = str.__new__(cls, code)
|
||||
|
||||
@ -67,7 +67,7 @@ class Code(str):
|
||||
|
||||
if scope is not None:
|
||||
if not isinstance(scope, _Mapping):
|
||||
raise TypeError("scope must be an instance of dict")
|
||||
raise TypeError(f"scope must be an instance of dict, not {type(scope)}")
|
||||
if self.__scope is not None:
|
||||
self.__scope.update(scope) # type: ignore
|
||||
else:
|
||||
|
||||
@ -401,17 +401,23 @@ else:
|
||||
"uuid_representation must be a value from bson.binary.UuidRepresentation"
|
||||
)
|
||||
if not isinstance(unicode_decode_error_handler, str):
|
||||
raise ValueError("unicode_decode_error_handler must be a string")
|
||||
raise ValueError(
|
||||
f"unicode_decode_error_handler must be a string, not {type(unicode_decode_error_handler)}"
|
||||
)
|
||||
if tzinfo is not None:
|
||||
if not isinstance(tzinfo, datetime.tzinfo):
|
||||
raise TypeError("tzinfo must be an instance of datetime.tzinfo")
|
||||
raise TypeError(
|
||||
f"tzinfo must be an instance of datetime.tzinfo, not {type(tzinfo)}"
|
||||
)
|
||||
if not tz_aware:
|
||||
raise ValueError("cannot specify tzinfo without also setting tz_aware=True")
|
||||
|
||||
type_registry = type_registry or TypeRegistry()
|
||||
|
||||
if not isinstance(type_registry, TypeRegistry):
|
||||
raise TypeError("type_registry must be an instance of TypeRegistry")
|
||||
raise TypeError(
|
||||
f"type_registry must be an instance of TypeRegistry, not {type(type_registry)}"
|
||||
)
|
||||
|
||||
return tuple.__new__(
|
||||
cls,
|
||||
|
||||
@ -56,9 +56,9 @@ class DBRef:
|
||||
.. seealso:: The MongoDB documentation on `dbrefs <https://dochub.mongodb.org/core/dbrefs>`_.
|
||||
"""
|
||||
if not isinstance(collection, str):
|
||||
raise TypeError("collection must be an instance of str")
|
||||
raise TypeError(f"collection must be an instance of str, not {type(collection)}")
|
||||
if database is not None and not isinstance(database, str):
|
||||
raise TypeError("database must be an instance of str")
|
||||
raise TypeError(f"database must be an instance of str, not {type(database)}")
|
||||
|
||||
self.__collection = collection
|
||||
self.__id = id
|
||||
|
||||
@ -277,7 +277,7 @@ class Decimal128:
|
||||
point in Binary Integer Decimal (BID) format).
|
||||
"""
|
||||
if not isinstance(value, bytes):
|
||||
raise TypeError("value must be an instance of bytes")
|
||||
raise TypeError(f"value must be an instance of bytes, not {type(value)}")
|
||||
if len(value) != 16:
|
||||
raise ValueError("value must be exactly 16 bytes")
|
||||
return cls((_UNPACK_64(value[8:])[0], _UNPACK_64(value[:8])[0])) # type: ignore
|
||||
|
||||
@ -58,9 +58,9 @@ class Timestamp:
|
||||
time = time - offset
|
||||
time = int(calendar.timegm(time.timetuple()))
|
||||
if not isinstance(time, int):
|
||||
raise TypeError("time must be an instance of int")
|
||||
raise TypeError(f"time must be an instance of int, not {type(time)}")
|
||||
if not isinstance(inc, int):
|
||||
raise TypeError("inc must be an instance of int")
|
||||
raise TypeError(f"inc must be an instance of int, not {type(inc)}")
|
||||
if not 0 <= time < UPPERBOUND:
|
||||
raise ValueError("time must be contained in [0, 2**32)")
|
||||
if not 0 <= inc < UPPERBOUND:
|
||||
|
||||
@ -100,7 +100,7 @@ class AsyncGridFS:
|
||||
.. seealso:: The MongoDB documentation on `gridfs <https://dochub.mongodb.org/core/gridfs>`_.
|
||||
"""
|
||||
if not isinstance(database, AsyncDatabase):
|
||||
raise TypeError("database must be an instance of Database")
|
||||
raise TypeError(f"database must be an instance of Database, not {type(database)}")
|
||||
|
||||
database = _clear_entity_type_registry(database)
|
||||
|
||||
@ -503,7 +503,7 @@ class AsyncGridFSBucket:
|
||||
.. seealso:: The MongoDB documentation on `gridfs <https://dochub.mongodb.org/core/gridfs>`_.
|
||||
"""
|
||||
if not isinstance(db, AsyncDatabase):
|
||||
raise TypeError("database must be an instance of AsyncDatabase")
|
||||
raise TypeError(f"database must be an instance of AsyncDatabase, not {type(db)}")
|
||||
|
||||
db = _clear_entity_type_registry(db)
|
||||
|
||||
@ -1082,7 +1082,9 @@ class AsyncGridIn:
|
||||
:attr:`~pymongo.collection.AsyncCollection.write_concern`
|
||||
"""
|
||||
if not isinstance(root_collection, AsyncCollection):
|
||||
raise TypeError("root_collection must be an instance of AsyncCollection")
|
||||
raise TypeError(
|
||||
f"root_collection must be an instance of AsyncCollection, not {type(root_collection)}"
|
||||
)
|
||||
|
||||
if not root_collection.write_concern.acknowledged:
|
||||
raise ConfigurationError("root_collection must use acknowledged write_concern")
|
||||
@ -1436,7 +1438,9 @@ class AsyncGridOut(GRIDOUT_BASE_CLASS): # type: ignore
|
||||
from the server. Metadata is fetched when first needed.
|
||||
"""
|
||||
if not isinstance(root_collection, AsyncCollection):
|
||||
raise TypeError("root_collection must be an instance of AsyncCollection")
|
||||
raise TypeError(
|
||||
f"root_collection must be an instance of AsyncCollection, not {type(root_collection)}"
|
||||
)
|
||||
_disallow_transactions(session)
|
||||
|
||||
root_collection = _clear_entity_type_registry(root_collection)
|
||||
|
||||
@ -100,7 +100,7 @@ class GridFS:
|
||||
.. seealso:: The MongoDB documentation on `gridfs <https://dochub.mongodb.org/core/gridfs>`_.
|
||||
"""
|
||||
if not isinstance(database, Database):
|
||||
raise TypeError("database must be an instance of Database")
|
||||
raise TypeError(f"database must be an instance of Database, not {type(database)}")
|
||||
|
||||
database = _clear_entity_type_registry(database)
|
||||
|
||||
@ -501,7 +501,7 @@ class GridFSBucket:
|
||||
.. seealso:: The MongoDB documentation on `gridfs <https://dochub.mongodb.org/core/gridfs>`_.
|
||||
"""
|
||||
if not isinstance(db, Database):
|
||||
raise TypeError("database must be an instance of Database")
|
||||
raise TypeError(f"database must be an instance of Database, not {type(db)}")
|
||||
|
||||
db = _clear_entity_type_registry(db)
|
||||
|
||||
@ -1076,7 +1076,9 @@ class GridIn:
|
||||
:attr:`~pymongo.collection.Collection.write_concern`
|
||||
"""
|
||||
if not isinstance(root_collection, Collection):
|
||||
raise TypeError("root_collection must be an instance of Collection")
|
||||
raise TypeError(
|
||||
f"root_collection must be an instance of Collection, not {type(root_collection)}"
|
||||
)
|
||||
|
||||
if not root_collection.write_concern.acknowledged:
|
||||
raise ConfigurationError("root_collection must use acknowledged write_concern")
|
||||
@ -1426,7 +1428,9 @@ class GridOut(GRIDOUT_BASE_CLASS): # type: ignore
|
||||
from the server. Metadata is fetched when first needed.
|
||||
"""
|
||||
if not isinstance(root_collection, Collection):
|
||||
raise TypeError("root_collection must be an instance of Collection")
|
||||
raise TypeError(
|
||||
f"root_collection must be an instance of Collection, not {type(root_collection)}"
|
||||
)
|
||||
_disallow_transactions(session)
|
||||
|
||||
root_collection = _clear_entity_type_registry(root_collection)
|
||||
|
||||
@ -160,7 +160,7 @@ def timeout(seconds: Optional[float]) -> ContextManager[None]:
|
||||
.. versionadded:: 4.2
|
||||
"""
|
||||
if not isinstance(seconds, (int, float, type(None))):
|
||||
raise TypeError("timeout must be None, an int, or a float")
|
||||
raise TypeError(f"timeout must be None, an int, or a float, not {type(seconds)}")
|
||||
if seconds and seconds < 0:
|
||||
raise ValueError("timeout cannot be negative")
|
||||
if seconds is not None:
|
||||
|
||||
@ -160,7 +160,7 @@ class Lock(_ContextManagerMixin, _LoopBoundMixin):
|
||||
self._locked = False
|
||||
self._wake_up_first()
|
||||
else:
|
||||
raise RuntimeError("Lock is not acquired.")
|
||||
raise RuntimeError("Lock is not acquired")
|
||||
|
||||
def _wake_up_first(self) -> None:
|
||||
"""Ensure that the first waiter will wake up."""
|
||||
|
||||
@ -46,7 +46,7 @@ def _get_azure_response(
|
||||
try:
|
||||
data = json.loads(body)
|
||||
except Exception:
|
||||
raise ValueError("Azure IMDS response must be in JSON format.") from None
|
||||
raise ValueError("Azure IMDS response must be in JSON format") from None
|
||||
|
||||
for key in ["access_token", "expires_in"]:
|
||||
if not data.get(key):
|
||||
|
||||
@ -161,7 +161,7 @@ def _password_digest(username: str, password: str) -> str:
|
||||
if len(password) == 0:
|
||||
raise ValueError("password can't be empty")
|
||||
if not isinstance(username, str):
|
||||
raise TypeError("username must be an instance of str")
|
||||
raise TypeError(f"username must be an instance of str, not {type(username)}")
|
||||
|
||||
md5hash = hashlib.md5() # noqa: S324
|
||||
data = f"{username}:mongo:{password}"
|
||||
|
||||
@ -213,7 +213,9 @@ class _OIDCAuthenticator:
|
||||
)
|
||||
resp = cb.fetch(context)
|
||||
if not isinstance(resp, OIDCCallbackResult):
|
||||
raise ValueError("Callback result must be of type OIDCCallbackResult")
|
||||
raise ValueError(
|
||||
f"Callback result must be of type OIDCCallbackResult, not {type(resp)}"
|
||||
)
|
||||
self.refresh_token = resp.refresh_token
|
||||
self.access_token = resp.access_token
|
||||
self.token_gen_id += 1
|
||||
|
||||
@ -310,7 +310,9 @@ class TransactionOptions:
|
||||
)
|
||||
if max_commit_time_ms is not None:
|
||||
if not isinstance(max_commit_time_ms, int):
|
||||
raise TypeError("max_commit_time_ms must be an integer or None")
|
||||
raise TypeError(
|
||||
f"max_commit_time_ms must be an integer or None, not {type(max_commit_time_ms)}"
|
||||
)
|
||||
|
||||
@property
|
||||
def read_concern(self) -> Optional[ReadConcern]:
|
||||
@ -902,7 +904,9 @@ class AsyncClientSession:
|
||||
another `AsyncClientSession` instance.
|
||||
"""
|
||||
if not isinstance(cluster_time, _Mapping):
|
||||
raise TypeError("cluster_time must be a subclass of collections.Mapping")
|
||||
raise TypeError(
|
||||
f"cluster_time must be a subclass of collections.Mapping, not {type(cluster_time)}"
|
||||
)
|
||||
if not isinstance(cluster_time.get("clusterTime"), Timestamp):
|
||||
raise ValueError("Invalid cluster_time")
|
||||
self._advance_cluster_time(cluster_time)
|
||||
@ -923,7 +927,9 @@ class AsyncClientSession:
|
||||
another `AsyncClientSession` instance.
|
||||
"""
|
||||
if not isinstance(operation_time, Timestamp):
|
||||
raise TypeError("operation_time must be an instance of bson.timestamp.Timestamp")
|
||||
raise TypeError(
|
||||
f"operation_time must be an instance of bson.timestamp.Timestamp, not {type(operation_time)}"
|
||||
)
|
||||
self._advance_operation_time(operation_time)
|
||||
|
||||
def _process_response(self, reply: Mapping[str, Any]) -> None:
|
||||
|
||||
@ -228,7 +228,7 @@ class AsyncCollection(common.BaseObject, Generic[_DocumentType]):
|
||||
read_concern or database.read_concern,
|
||||
)
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name must be an instance of str")
|
||||
raise TypeError(f"name must be an instance of str, not {type(name)}")
|
||||
from pymongo.asynchronous.database import AsyncDatabase
|
||||
|
||||
if not isinstance(database, AsyncDatabase):
|
||||
@ -2475,7 +2475,7 @@ class AsyncCollection(common.BaseObject, Generic[_DocumentType]):
|
||||
name = helpers_shared._gen_index_name(index_or_name)
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("index_or_name must be an instance of str or list")
|
||||
raise TypeError(f"index_or_name must be an instance of str or list, not {type(name)}")
|
||||
|
||||
cmd = {"dropIndexes": self._name, "index": name}
|
||||
cmd.update(kwargs)
|
||||
@ -3078,7 +3078,7 @@ class AsyncCollection(common.BaseObject, Generic[_DocumentType]):
|
||||
|
||||
"""
|
||||
if not isinstance(new_name, str):
|
||||
raise TypeError("new_name must be an instance of str")
|
||||
raise TypeError(f"new_name must be an instance of str, not {type(new_name)}")
|
||||
|
||||
if not new_name or ".." in new_name:
|
||||
raise InvalidName("collection names cannot be empty")
|
||||
@ -3148,7 +3148,7 @@ class AsyncCollection(common.BaseObject, Generic[_DocumentType]):
|
||||
|
||||
"""
|
||||
if not isinstance(key, str):
|
||||
raise TypeError("key must be an instance of str")
|
||||
raise TypeError(f"key must be an instance of str, not {type(key)}")
|
||||
cmd = {"distinct": self._name, "key": key}
|
||||
if filter is not None:
|
||||
if "query" in kwargs:
|
||||
@ -3196,7 +3196,7 @@ class AsyncCollection(common.BaseObject, Generic[_DocumentType]):
|
||||
common.validate_is_mapping("filter", filter)
|
||||
if not isinstance(return_document, bool):
|
||||
raise ValueError(
|
||||
"return_document must be ReturnDocument.BEFORE or ReturnDocument.AFTER"
|
||||
f"return_document must be ReturnDocument.BEFORE or ReturnDocument.AFTER, not {type(return_document)}"
|
||||
)
|
||||
collation = validate_collation_or_none(kwargs.pop("collation", None))
|
||||
cmd = {"findAndModify": self._name, "query": filter, "new": return_document}
|
||||
|
||||
@ -94,7 +94,9 @@ class AsyncCommandCursor(Generic[_DocumentType]):
|
||||
self.batch_size(batch_size)
|
||||
|
||||
if not isinstance(max_await_time_ms, int) and max_await_time_ms is not None:
|
||||
raise TypeError("max_await_time_ms must be an integer or None")
|
||||
raise TypeError(
|
||||
f"max_await_time_ms must be an integer or None, not {type(max_await_time_ms)}"
|
||||
)
|
||||
|
||||
def __del__(self) -> None:
|
||||
self._die_no_lock()
|
||||
@ -115,7 +117,7 @@ class AsyncCommandCursor(Generic[_DocumentType]):
|
||||
:param batch_size: The size of each batch of results requested.
|
||||
"""
|
||||
if not isinstance(batch_size, int):
|
||||
raise TypeError("batch_size must be an integer")
|
||||
raise TypeError(f"batch_size must be an integer, not {type(batch_size)}")
|
||||
if batch_size < 0:
|
||||
raise ValueError("batch_size must be >= 0")
|
||||
|
||||
|
||||
@ -146,9 +146,9 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
spec: Mapping[str, Any] = filter or {}
|
||||
validate_is_mapping("filter", spec)
|
||||
if not isinstance(skip, int):
|
||||
raise TypeError("skip must be an instance of int")
|
||||
raise TypeError(f"skip must be an instance of int, not {type(skip)}")
|
||||
if not isinstance(limit, int):
|
||||
raise TypeError("limit must be an instance of int")
|
||||
raise TypeError(f"limit must be an instance of int, not {type(limit)}")
|
||||
validate_boolean("no_cursor_timeout", no_cursor_timeout)
|
||||
if no_cursor_timeout and not self._explicit_session:
|
||||
warnings.warn(
|
||||
@ -171,7 +171,7 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
validate_boolean("allow_partial_results", allow_partial_results)
|
||||
validate_boolean("oplog_replay", oplog_replay)
|
||||
if not isinstance(batch_size, int):
|
||||
raise TypeError("batch_size must be an integer")
|
||||
raise TypeError(f"batch_size must be an integer, not {type(batch_size)}")
|
||||
if batch_size < 0:
|
||||
raise ValueError("batch_size must be >= 0")
|
||||
# Only set if allow_disk_use is provided by the user, else None.
|
||||
@ -388,7 +388,7 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
cursor.add_option(2)
|
||||
"""
|
||||
if not isinstance(mask, int):
|
||||
raise TypeError("mask must be an int")
|
||||
raise TypeError(f"mask must be an int, not {type(mask)}")
|
||||
self._check_okay_to_chain()
|
||||
|
||||
if mask & _QUERY_OPTIONS["exhaust"]:
|
||||
@ -408,7 +408,7 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
cursor.remove_option(2)
|
||||
"""
|
||||
if not isinstance(mask, int):
|
||||
raise TypeError("mask must be an int")
|
||||
raise TypeError(f"mask must be an int, not {type(mask)}")
|
||||
self._check_okay_to_chain()
|
||||
|
||||
if mask & _QUERY_OPTIONS["exhaust"]:
|
||||
@ -432,7 +432,7 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
.. versionadded:: 3.11
|
||||
"""
|
||||
if not isinstance(allow_disk_use, bool):
|
||||
raise TypeError("allow_disk_use must be a bool")
|
||||
raise TypeError(f"allow_disk_use must be a bool, not {type(allow_disk_use)}")
|
||||
self._check_okay_to_chain()
|
||||
|
||||
self._allow_disk_use = allow_disk_use
|
||||
@ -451,7 +451,7 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
.. seealso:: The MongoDB documentation on `limit <https://dochub.mongodb.org/core/limit>`_.
|
||||
"""
|
||||
if not isinstance(limit, int):
|
||||
raise TypeError("limit must be an integer")
|
||||
raise TypeError(f"limit must be an integer, not {type(limit)}")
|
||||
if self._exhaust:
|
||||
raise InvalidOperation("Can't use limit and exhaust together.")
|
||||
self._check_okay_to_chain()
|
||||
@ -479,7 +479,7 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
:param batch_size: The size of each batch of results requested.
|
||||
"""
|
||||
if not isinstance(batch_size, int):
|
||||
raise TypeError("batch_size must be an integer")
|
||||
raise TypeError(f"batch_size must be an integer, not {type(batch_size)}")
|
||||
if batch_size < 0:
|
||||
raise ValueError("batch_size must be >= 0")
|
||||
self._check_okay_to_chain()
|
||||
@ -499,7 +499,7 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
:param skip: the number of results to skip
|
||||
"""
|
||||
if not isinstance(skip, int):
|
||||
raise TypeError("skip must be an integer")
|
||||
raise TypeError(f"skip must be an integer, not {type(skip)}")
|
||||
if skip < 0:
|
||||
raise ValueError("skip must be >= 0")
|
||||
self._check_okay_to_chain()
|
||||
@ -520,7 +520,7 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
:param max_time_ms: the time limit after which the operation is aborted
|
||||
"""
|
||||
if not isinstance(max_time_ms, int) and max_time_ms is not None:
|
||||
raise TypeError("max_time_ms must be an integer or None")
|
||||
raise TypeError(f"max_time_ms must be an integer or None, not {type(max_time_ms)}")
|
||||
self._check_okay_to_chain()
|
||||
|
||||
self._max_time_ms = max_time_ms
|
||||
@ -543,7 +543,9 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
.. versionadded:: 3.2
|
||||
"""
|
||||
if not isinstance(max_await_time_ms, int) and max_await_time_ms is not None:
|
||||
raise TypeError("max_await_time_ms must be an integer or None")
|
||||
raise TypeError(
|
||||
f"max_await_time_ms must be an integer or None, not {type(max_await_time_ms)}"
|
||||
)
|
||||
self._check_okay_to_chain()
|
||||
|
||||
# Ignore max_await_time_ms if not tailable or await_data is False.
|
||||
@ -679,7 +681,7 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
.. versionadded:: 2.7
|
||||
"""
|
||||
if not isinstance(spec, (list, tuple)):
|
||||
raise TypeError("spec must be an instance of list or tuple")
|
||||
raise TypeError(f"spec must be an instance of list or tuple, not {type(spec)}")
|
||||
|
||||
self._check_okay_to_chain()
|
||||
self._max = dict(spec)
|
||||
@ -701,7 +703,7 @@ class AsyncCursor(Generic[_DocumentType]):
|
||||
.. versionadded:: 2.7
|
||||
"""
|
||||
if not isinstance(spec, (list, tuple)):
|
||||
raise TypeError("spec must be an instance of list or tuple")
|
||||
raise TypeError(f"spec must be an instance of list or tuple, not {type(spec)}")
|
||||
|
||||
self._check_okay_to_chain()
|
||||
self._min = dict(spec)
|
||||
|
||||
@ -122,7 +122,7 @@ class AsyncDatabase(common.BaseObject, Generic[_DocumentType]):
|
||||
from pymongo.asynchronous.mongo_client import AsyncMongoClient
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name must be an instance of str")
|
||||
raise TypeError(f"name must be an instance of str, not {type(name)}")
|
||||
|
||||
if not isinstance(client, AsyncMongoClient):
|
||||
# This is for compatibility with mocked and subclassed types, such as in Motor.
|
||||
@ -1310,7 +1310,7 @@ class AsyncDatabase(common.BaseObject, Generic[_DocumentType]):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name_or_collection must be an instance of str")
|
||||
raise TypeError(f"name_or_collection must be an instance of str, not {type(name)}")
|
||||
encrypted_fields = await self._get_encrypted_fields(
|
||||
{"encryptedFields": encrypted_fields},
|
||||
name,
|
||||
@ -1374,7 +1374,9 @@ class AsyncDatabase(common.BaseObject, Generic[_DocumentType]):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name_or_collection must be an instance of str or AsyncCollection")
|
||||
raise TypeError(
|
||||
f"name_or_collection must be an instance of str or AsyncCollection, not {type(name)}"
|
||||
)
|
||||
cmd = {"validate": name, "scandata": scandata, "full": full}
|
||||
if comment is not None:
|
||||
cmd["comment"] = comment
|
||||
|
||||
@ -322,7 +322,9 @@ class _EncryptionIO(AsyncMongoCryptCallback): # type: ignore[misc]
|
||||
raw_doc = RawBSONDocument(data_key, _KEY_VAULT_OPTS)
|
||||
data_key_id = raw_doc.get("_id")
|
||||
if not isinstance(data_key_id, Binary) or data_key_id.subtype != UUID_SUBTYPE:
|
||||
raise TypeError("data_key _id must be Binary with a UUID subtype")
|
||||
raise TypeError(
|
||||
f"data_key _id must be Binary with a UUID subtype, not {type(data_key_id)}"
|
||||
)
|
||||
|
||||
assert self.key_vault_coll is not None
|
||||
await self.key_vault_coll.insert_one(raw_doc)
|
||||
@ -644,7 +646,9 @@ class AsyncClientEncryption(Generic[_DocumentType]):
|
||||
)
|
||||
|
||||
if not isinstance(codec_options, CodecOptions):
|
||||
raise TypeError("codec_options must be an instance of bson.codec_options.CodecOptions")
|
||||
raise TypeError(
|
||||
f"codec_options must be an instance of bson.codec_options.CodecOptions, not {type(codec_options)}"
|
||||
)
|
||||
|
||||
if not isinstance(key_vault_client, AsyncMongoClient):
|
||||
# This is for compatibility with mocked and subclassed types, such as in Motor.
|
||||
|
||||
@ -750,7 +750,7 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
if port is None:
|
||||
port = self.PORT
|
||||
if not isinstance(port, int):
|
||||
raise TypeError("port must be an instance of int")
|
||||
raise TypeError(f"port must be an instance of int, not {type(port)}")
|
||||
|
||||
# _pool_class, _monitor_class, and _condition_class are for deep
|
||||
# customization of PyMongo, e.g. Motor.
|
||||
@ -1971,7 +1971,7 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
The cursor is closed synchronously on the current thread.
|
||||
"""
|
||||
if not isinstance(cursor_id, int):
|
||||
raise TypeError("cursor_id must be an instance of int")
|
||||
raise TypeError(f"cursor_id must be an instance of int, not {type(cursor_id)}")
|
||||
|
||||
try:
|
||||
if conn_mgr:
|
||||
@ -2093,7 +2093,9 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
"""If provided session is None, lend a temporary session."""
|
||||
if session is not None:
|
||||
if not isinstance(session, client_session.AsyncClientSession):
|
||||
raise ValueError("'session' argument must be an AsyncClientSession or None.")
|
||||
raise ValueError(
|
||||
f"'session' argument must be an AsyncClientSession or None, not {type(session)}"
|
||||
)
|
||||
# Don't call end_session.
|
||||
yield session
|
||||
return
|
||||
@ -2247,7 +2249,9 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name_or_database must be an instance of str or a AsyncDatabase")
|
||||
raise TypeError(
|
||||
f"name_or_database must be an instance of str or a AsyncDatabase, not {type(name)}"
|
||||
)
|
||||
|
||||
async with await self._conn_for_writes(session, operation=_Op.DROP_DATABASE) as conn:
|
||||
await self[name]._command(
|
||||
|
||||
@ -107,7 +107,7 @@ def _build_credentials_tuple(
|
||||
) -> MongoCredential:
|
||||
"""Build and return a mechanism specific credentials tuple."""
|
||||
if mech not in ("MONGODB-X509", "MONGODB-AWS", "MONGODB-OIDC") and user is None:
|
||||
raise ConfigurationError(f"{mech} requires a username.")
|
||||
raise ConfigurationError(f"{mech} requires a username")
|
||||
if mech == "GSSAPI":
|
||||
if source is not None and source != "$external":
|
||||
raise ValueError("authentication source must be $external or None for GSSAPI")
|
||||
@ -219,7 +219,7 @@ def _build_credentials_tuple(
|
||||
else:
|
||||
source_database = source or database or "admin"
|
||||
if passwd is None:
|
||||
raise ConfigurationError("A password is required.")
|
||||
raise ConfigurationError("A password is required")
|
||||
return MongoCredential(mech, source_database, user, passwd, None, _Cache())
|
||||
|
||||
|
||||
|
||||
@ -223,4 +223,4 @@ def validate_collation_or_none(
|
||||
return value.document
|
||||
if isinstance(value, dict):
|
||||
return value
|
||||
raise TypeError("collation must be a dict, an instance of collation.Collation, or None.")
|
||||
raise TypeError("collation must be a dict, an instance of collation.Collation, or None")
|
||||
|
||||
@ -202,7 +202,7 @@ def validate_integer(option: str, value: Any) -> int:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
raise ValueError(f"The value of {option} must be an integer") from None
|
||||
raise TypeError(f"Wrong type for {option}, value must be an integer")
|
||||
raise TypeError(f"Wrong type for {option}, value must be an integer, not {type(value)}")
|
||||
|
||||
|
||||
def validate_positive_integer(option: str, value: Any) -> int:
|
||||
@ -250,7 +250,7 @@ def validate_string(option: str, value: Any) -> str:
|
||||
"""Validates that 'value' is an instance of `str`."""
|
||||
if isinstance(value, str):
|
||||
return value
|
||||
raise TypeError(f"Wrong type for {option}, value must be an instance of str")
|
||||
raise TypeError(f"Wrong type for {option}, value must be an instance of str, not {type(value)}")
|
||||
|
||||
|
||||
def validate_string_or_none(option: str, value: Any) -> Optional[str]:
|
||||
@ -269,7 +269,9 @@ def validate_int_or_basestring(option: str, value: Any) -> Union[int, str]:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
return value
|
||||
raise TypeError(f"Wrong type for {option}, value must be an integer or a string")
|
||||
raise TypeError(
|
||||
f"Wrong type for {option}, value must be an integer or a string, not {type(value)}"
|
||||
)
|
||||
|
||||
|
||||
def validate_non_negative_int_or_basestring(option: Any, value: Any) -> Union[int, str]:
|
||||
@ -282,7 +284,9 @@ def validate_non_negative_int_or_basestring(option: Any, value: Any) -> Union[in
|
||||
except ValueError:
|
||||
return value
|
||||
return validate_non_negative_integer(option, val)
|
||||
raise TypeError(f"Wrong type for {option}, value must be an non negative integer or a string")
|
||||
raise TypeError(
|
||||
f"Wrong type for {option}, value must be an non negative integer or a string, not {type(value)}"
|
||||
)
|
||||
|
||||
|
||||
def validate_positive_float(option: str, value: Any) -> float:
|
||||
@ -365,7 +369,7 @@ def validate_max_staleness(option: str, value: Any) -> int:
|
||||
def validate_read_preference(dummy: Any, value: Any) -> _ServerMode:
|
||||
"""Validate a read preference."""
|
||||
if not isinstance(value, _ServerMode):
|
||||
raise TypeError(f"{value!r} is not a read preference.")
|
||||
raise TypeError(f"{value!r} is not a read preference")
|
||||
return value
|
||||
|
||||
|
||||
@ -441,7 +445,9 @@ def validate_auth_mechanism_properties(option: str, value: Any) -> dict[str, Uni
|
||||
props: dict[str, Any] = {}
|
||||
if not isinstance(value, str):
|
||||
if not isinstance(value, dict):
|
||||
raise ValueError("Auth mechanism properties must be given as a string or a dictionary")
|
||||
raise ValueError(
|
||||
f"Auth mechanism properties must be given as a string or a dictionary, not {type(value)}"
|
||||
)
|
||||
for key, value in value.items(): # noqa: B020
|
||||
if isinstance(value, str):
|
||||
props[key] = value
|
||||
@ -453,7 +459,7 @@ def validate_auth_mechanism_properties(option: str, value: Any) -> dict[str, Uni
|
||||
from pymongo.auth_oidc_shared import OIDCCallback
|
||||
|
||||
if not isinstance(value, OIDCCallback):
|
||||
raise ValueError("callback must be an OIDCCallback object")
|
||||
raise ValueError(f"callback must be an OIDCCallback object, not {type(value)}")
|
||||
props[key] = value
|
||||
else:
|
||||
raise ValueError(f"Invalid type for auth mechanism property {key}, {type(value)}")
|
||||
@ -476,7 +482,7 @@ def validate_auth_mechanism_properties(option: str, value: Any) -> dict[str, Uni
|
||||
raise ValueError(
|
||||
f"{key} is not a supported auth "
|
||||
"mechanism property. Must be one of "
|
||||
f"{tuple(_MECHANISM_PROPS)}."
|
||||
f"{tuple(_MECHANISM_PROPS)}"
|
||||
)
|
||||
|
||||
if key == "CANONICALIZE_HOST_NAME":
|
||||
@ -520,7 +526,7 @@ def validate_type_registry(option: Any, value: Any) -> Optional[TypeRegistry]:
|
||||
def validate_list(option: str, value: Any) -> list:
|
||||
"""Validates that 'value' is a list."""
|
||||
if not isinstance(value, list):
|
||||
raise TypeError(f"{option} must be a list")
|
||||
raise TypeError(f"{option} must be a list, not {type(value)}")
|
||||
return value
|
||||
|
||||
|
||||
@ -587,7 +593,7 @@ def validate_server_api_or_none(option: Any, value: Any) -> Optional[ServerApi]:
|
||||
if value is None:
|
||||
return value
|
||||
if not isinstance(value, ServerApi):
|
||||
raise TypeError(f"{option} must be an instance of ServerApi")
|
||||
raise TypeError(f"{option} must be an instance of ServerApi, not {type(value)}")
|
||||
return value
|
||||
|
||||
|
||||
@ -596,7 +602,7 @@ def validate_is_callable_or_none(option: Any, value: Any) -> Optional[Callable]:
|
||||
if value is None:
|
||||
return value
|
||||
if not callable(value):
|
||||
raise ValueError(f"{option} must be a callable")
|
||||
raise ValueError(f"{option} must be a callable, not {type(value)}")
|
||||
return value
|
||||
|
||||
|
||||
@ -651,7 +657,7 @@ def validate_auto_encryption_opts_or_none(option: Any, value: Any) -> Optional[A
|
||||
from pymongo.encryption_options import AutoEncryptionOpts
|
||||
|
||||
if not isinstance(value, AutoEncryptionOpts):
|
||||
raise TypeError(f"{option} must be an instance of AutoEncryptionOpts")
|
||||
raise TypeError(f"{option} must be an instance of AutoEncryptionOpts, not {type(value)}")
|
||||
|
||||
return value
|
||||
|
||||
@ -668,7 +674,9 @@ def validate_datetime_conversion(option: Any, value: Any) -> Optional[DatetimeCo
|
||||
elif isinstance(value, int):
|
||||
return DatetimeConversion(value)
|
||||
|
||||
raise TypeError(f"{option} must be a str or int representing DatetimeConversion")
|
||||
raise TypeError(
|
||||
f"{option} must be a str or int representing DatetimeConversion, not {type(value)}"
|
||||
)
|
||||
|
||||
|
||||
def validate_server_monitoring_mode(option: str, value: str) -> str:
|
||||
@ -928,12 +936,14 @@ class BaseObject:
|
||||
|
||||
if not isinstance(write_concern, WriteConcern):
|
||||
raise TypeError(
|
||||
"write_concern must be an instance of pymongo.write_concern.WriteConcern"
|
||||
f"write_concern must be an instance of pymongo.write_concern.WriteConcern, not {type(write_concern)}"
|
||||
)
|
||||
self._write_concern = write_concern
|
||||
|
||||
if not isinstance(read_concern, ReadConcern):
|
||||
raise TypeError("read_concern must be an instance of pymongo.read_concern.ReadConcern")
|
||||
raise TypeError(
|
||||
f"read_concern must be an instance of pymongo.read_concern.ReadConcern, not {type(read_concern)}"
|
||||
)
|
||||
self._read_concern = read_concern
|
||||
|
||||
@property
|
||||
|
||||
@ -91,7 +91,7 @@ def validate_zlib_compression_level(option: str, value: Any) -> int:
|
||||
try:
|
||||
level = int(value)
|
||||
except Exception:
|
||||
raise TypeError(f"{option} must be an integer, not {value!r}.") from None
|
||||
raise TypeError(f"{option} must be an integer, not {value!r}") from None
|
||||
if level < -1 or level > 9:
|
||||
raise ValueError("%s must be between -1 and 9, not %d." % (option, level))
|
||||
return level
|
||||
|
||||
@ -39,7 +39,7 @@ class DriverInfo(namedtuple("DriverInfo", ["name", "version", "platform"])):
|
||||
for key, value in self._asdict().items():
|
||||
if value is not None and not isinstance(value, str):
|
||||
raise TypeError(
|
||||
f"Wrong type for DriverInfo {key} option, value must be an instance of str"
|
||||
f"Wrong type for DriverInfo {key} option, value must be an instance of str, not {type(value)}"
|
||||
)
|
||||
|
||||
return self
|
||||
|
||||
@ -225,7 +225,9 @@ class AutoEncryptionOpts:
|
||||
mongocryptd_spawn_args = ["--idleShutdownTimeoutSecs=60"]
|
||||
self._mongocryptd_spawn_args = mongocryptd_spawn_args
|
||||
if not isinstance(self._mongocryptd_spawn_args, list):
|
||||
raise TypeError("mongocryptd_spawn_args must be a list")
|
||||
raise TypeError(
|
||||
f"mongocryptd_spawn_args must be a list, not {type(self._mongocryptd_spawn_args)}"
|
||||
)
|
||||
if not any("idleShutdownTimeoutSecs" in s for s in self._mongocryptd_spawn_args):
|
||||
self._mongocryptd_spawn_args.append("--idleShutdownTimeoutSecs=60")
|
||||
# Maps KMS provider name to a SSLContext.
|
||||
|
||||
@ -122,7 +122,7 @@ def _index_list(
|
||||
"""
|
||||
if direction is not None:
|
||||
if not isinstance(key_or_list, str):
|
||||
raise TypeError("Expected a string and a direction")
|
||||
raise TypeError(f"Expected a string and a direction, not {type(key_or_list)}")
|
||||
return [(key_or_list, direction)]
|
||||
else:
|
||||
if isinstance(key_or_list, str):
|
||||
@ -132,7 +132,9 @@ def _index_list(
|
||||
elif isinstance(key_or_list, abc.Mapping):
|
||||
return list(key_or_list.items())
|
||||
elif not isinstance(key_or_list, (list, tuple)):
|
||||
raise TypeError("if no direction is specified, key_or_list must be an instance of list")
|
||||
raise TypeError(
|
||||
f"if no direction is specified, key_or_list must be an instance of list, not {type(key_or_list)}"
|
||||
)
|
||||
values: list[tuple[str, int]] = []
|
||||
for item in key_or_list:
|
||||
if isinstance(item, str):
|
||||
@ -172,11 +174,12 @@ def _index_document(index_list: _IndexList) -> dict[str, Any]:
|
||||
|
||||
def _validate_index_key_pair(key: Any, value: Any) -> None:
|
||||
if not isinstance(key, str):
|
||||
raise TypeError("first item in each key pair must be an instance of str")
|
||||
raise TypeError(f"first item in each key pair must be an instance of str, not {type(key)}")
|
||||
if not isinstance(value, (str, int, abc.Mapping)):
|
||||
raise TypeError(
|
||||
"second item in each key pair must be 1, -1, "
|
||||
"'2d', or another valid MongoDB index specifier."
|
||||
f", not {type(value)}"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -472,14 +472,15 @@ def _validate_event_listeners(
|
||||
) -> Sequence[_EventListeners]:
|
||||
"""Validate event listeners"""
|
||||
if not isinstance(listeners, abc.Sequence):
|
||||
raise TypeError(f"{option} must be a list or tuple")
|
||||
raise TypeError(f"{option} must be a list or tuple, not {type(listeners)}")
|
||||
for listener in listeners:
|
||||
if not isinstance(listener, _EventListener):
|
||||
raise TypeError(
|
||||
f"Listeners for {option} must be either a "
|
||||
"CommandListener, ServerHeartbeatListener, "
|
||||
"ServerListener, TopologyListener, or "
|
||||
"ConnectionPoolListener."
|
||||
"ConnectionPoolListener,"
|
||||
f"not {type(listener)}"
|
||||
)
|
||||
return listeners
|
||||
|
||||
@ -496,7 +497,8 @@ def register(listener: _EventListener) -> None:
|
||||
f"Listeners for {listener} must be either a "
|
||||
"CommandListener, ServerHeartbeatListener, "
|
||||
"ServerListener, TopologyListener, or "
|
||||
"ConnectionPoolListener."
|
||||
"ConnectionPoolListener,"
|
||||
f"not {type(listener)}"
|
||||
)
|
||||
if isinstance(listener, CommandListener):
|
||||
_LISTENERS.command_listeners.append(listener)
|
||||
|
||||
@ -38,7 +38,7 @@ class ReadConcern:
|
||||
if level is None or isinstance(level, str):
|
||||
self.__level = level
|
||||
else:
|
||||
raise TypeError("level must be a string or None.")
|
||||
raise TypeError(f"level must be a string or None, not {type(level)}")
|
||||
|
||||
@property
|
||||
def level(self) -> Optional[str]:
|
||||
|
||||
@ -115,4 +115,4 @@ else:
|
||||
|
||||
def get_ssl_context(*dummy): # type: ignore
|
||||
"""No ssl module, raise ConfigurationError."""
|
||||
raise ConfigurationError("The ssl module is not available.")
|
||||
raise ConfigurationError("The ssl module is not available")
|
||||
|
||||
@ -158,7 +158,7 @@ def _password_digest(username: str, password: str) -> str:
|
||||
if len(password) == 0:
|
||||
raise ValueError("password can't be empty")
|
||||
if not isinstance(username, str):
|
||||
raise TypeError("username must be an instance of str")
|
||||
raise TypeError(f"username must be an instance of str, not {type(username)}")
|
||||
|
||||
md5hash = hashlib.md5() # noqa: S324
|
||||
data = f"{username}:mongo:{password}"
|
||||
|
||||
@ -213,7 +213,9 @@ class _OIDCAuthenticator:
|
||||
)
|
||||
resp = cb.fetch(context)
|
||||
if not isinstance(resp, OIDCCallbackResult):
|
||||
raise ValueError("Callback result must be of type OIDCCallbackResult")
|
||||
raise ValueError(
|
||||
f"Callback result must be of type OIDCCallbackResult, not {type(resp)}"
|
||||
)
|
||||
self.refresh_token = resp.refresh_token
|
||||
self.access_token = resp.access_token
|
||||
self.token_gen_id += 1
|
||||
|
||||
@ -309,7 +309,9 @@ class TransactionOptions:
|
||||
)
|
||||
if max_commit_time_ms is not None:
|
||||
if not isinstance(max_commit_time_ms, int):
|
||||
raise TypeError("max_commit_time_ms must be an integer or None")
|
||||
raise TypeError(
|
||||
f"max_commit_time_ms must be an integer or None, not {type(max_commit_time_ms)}"
|
||||
)
|
||||
|
||||
@property
|
||||
def read_concern(self) -> Optional[ReadConcern]:
|
||||
@ -897,7 +899,9 @@ class ClientSession:
|
||||
another `ClientSession` instance.
|
||||
"""
|
||||
if not isinstance(cluster_time, _Mapping):
|
||||
raise TypeError("cluster_time must be a subclass of collections.Mapping")
|
||||
raise TypeError(
|
||||
f"cluster_time must be a subclass of collections.Mapping, not {type(cluster_time)}"
|
||||
)
|
||||
if not isinstance(cluster_time.get("clusterTime"), Timestamp):
|
||||
raise ValueError("Invalid cluster_time")
|
||||
self._advance_cluster_time(cluster_time)
|
||||
@ -918,7 +922,9 @@ class ClientSession:
|
||||
another `ClientSession` instance.
|
||||
"""
|
||||
if not isinstance(operation_time, Timestamp):
|
||||
raise TypeError("operation_time must be an instance of bson.timestamp.Timestamp")
|
||||
raise TypeError(
|
||||
f"operation_time must be an instance of bson.timestamp.Timestamp, not {type(operation_time)}"
|
||||
)
|
||||
self._advance_operation_time(operation_time)
|
||||
|
||||
def _process_response(self, reply: Mapping[str, Any]) -> None:
|
||||
|
||||
@ -231,7 +231,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
|
||||
read_concern or database.read_concern,
|
||||
)
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name must be an instance of str")
|
||||
raise TypeError(f"name must be an instance of str, not {type(name)}")
|
||||
from pymongo.synchronous.database import Database
|
||||
|
||||
if not isinstance(database, Database):
|
||||
@ -2472,7 +2472,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
|
||||
name = helpers_shared._gen_index_name(index_or_name)
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("index_or_name must be an instance of str or list")
|
||||
raise TypeError(f"index_or_name must be an instance of str or list, not {type(name)}")
|
||||
|
||||
cmd = {"dropIndexes": self._name, "index": name}
|
||||
cmd.update(kwargs)
|
||||
@ -3071,7 +3071,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
|
||||
|
||||
"""
|
||||
if not isinstance(new_name, str):
|
||||
raise TypeError("new_name must be an instance of str")
|
||||
raise TypeError(f"new_name must be an instance of str, not {type(new_name)}")
|
||||
|
||||
if not new_name or ".." in new_name:
|
||||
raise InvalidName("collection names cannot be empty")
|
||||
@ -3141,7 +3141,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
|
||||
|
||||
"""
|
||||
if not isinstance(key, str):
|
||||
raise TypeError("key must be an instance of str")
|
||||
raise TypeError(f"key must be an instance of str, not {type(key)}")
|
||||
cmd = {"distinct": self._name, "key": key}
|
||||
if filter is not None:
|
||||
if "query" in kwargs:
|
||||
@ -3189,7 +3189,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
|
||||
common.validate_is_mapping("filter", filter)
|
||||
if not isinstance(return_document, bool):
|
||||
raise ValueError(
|
||||
"return_document must be ReturnDocument.BEFORE or ReturnDocument.AFTER"
|
||||
f"return_document must be ReturnDocument.BEFORE or ReturnDocument.AFTER, not {type(return_document)}"
|
||||
)
|
||||
collation = validate_collation_or_none(kwargs.pop("collation", None))
|
||||
cmd = {"findAndModify": self._name, "query": filter, "new": return_document}
|
||||
|
||||
@ -94,7 +94,9 @@ class CommandCursor(Generic[_DocumentType]):
|
||||
self.batch_size(batch_size)
|
||||
|
||||
if not isinstance(max_await_time_ms, int) and max_await_time_ms is not None:
|
||||
raise TypeError("max_await_time_ms must be an integer or None")
|
||||
raise TypeError(
|
||||
f"max_await_time_ms must be an integer or None, not {type(max_await_time_ms)}"
|
||||
)
|
||||
|
||||
def __del__(self) -> None:
|
||||
self._die_no_lock()
|
||||
@ -115,7 +117,7 @@ class CommandCursor(Generic[_DocumentType]):
|
||||
:param batch_size: The size of each batch of results requested.
|
||||
"""
|
||||
if not isinstance(batch_size, int):
|
||||
raise TypeError("batch_size must be an integer")
|
||||
raise TypeError(f"batch_size must be an integer, not {type(batch_size)}")
|
||||
if batch_size < 0:
|
||||
raise ValueError("batch_size must be >= 0")
|
||||
|
||||
|
||||
@ -146,9 +146,9 @@ class Cursor(Generic[_DocumentType]):
|
||||
spec: Mapping[str, Any] = filter or {}
|
||||
validate_is_mapping("filter", spec)
|
||||
if not isinstance(skip, int):
|
||||
raise TypeError("skip must be an instance of int")
|
||||
raise TypeError(f"skip must be an instance of int, not {type(skip)}")
|
||||
if not isinstance(limit, int):
|
||||
raise TypeError("limit must be an instance of int")
|
||||
raise TypeError(f"limit must be an instance of int, not {type(limit)}")
|
||||
validate_boolean("no_cursor_timeout", no_cursor_timeout)
|
||||
if no_cursor_timeout and not self._explicit_session:
|
||||
warnings.warn(
|
||||
@ -171,7 +171,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
validate_boolean("allow_partial_results", allow_partial_results)
|
||||
validate_boolean("oplog_replay", oplog_replay)
|
||||
if not isinstance(batch_size, int):
|
||||
raise TypeError("batch_size must be an integer")
|
||||
raise TypeError(f"batch_size must be an integer, not {type(batch_size)}")
|
||||
if batch_size < 0:
|
||||
raise ValueError("batch_size must be >= 0")
|
||||
# Only set if allow_disk_use is provided by the user, else None.
|
||||
@ -388,7 +388,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
cursor.add_option(2)
|
||||
"""
|
||||
if not isinstance(mask, int):
|
||||
raise TypeError("mask must be an int")
|
||||
raise TypeError(f"mask must be an int, not {type(mask)}")
|
||||
self._check_okay_to_chain()
|
||||
|
||||
if mask & _QUERY_OPTIONS["exhaust"]:
|
||||
@ -408,7 +408,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
cursor.remove_option(2)
|
||||
"""
|
||||
if not isinstance(mask, int):
|
||||
raise TypeError("mask must be an int")
|
||||
raise TypeError(f"mask must be an int, not {type(mask)}")
|
||||
self._check_okay_to_chain()
|
||||
|
||||
if mask & _QUERY_OPTIONS["exhaust"]:
|
||||
@ -432,7 +432,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
.. versionadded:: 3.11
|
||||
"""
|
||||
if not isinstance(allow_disk_use, bool):
|
||||
raise TypeError("allow_disk_use must be a bool")
|
||||
raise TypeError(f"allow_disk_use must be a bool, not {type(allow_disk_use)}")
|
||||
self._check_okay_to_chain()
|
||||
|
||||
self._allow_disk_use = allow_disk_use
|
||||
@ -451,7 +451,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
.. seealso:: The MongoDB documentation on `limit <https://dochub.mongodb.org/core/limit>`_.
|
||||
"""
|
||||
if not isinstance(limit, int):
|
||||
raise TypeError("limit must be an integer")
|
||||
raise TypeError(f"limit must be an integer, not {type(limit)}")
|
||||
if self._exhaust:
|
||||
raise InvalidOperation("Can't use limit and exhaust together.")
|
||||
self._check_okay_to_chain()
|
||||
@ -479,7 +479,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
:param batch_size: The size of each batch of results requested.
|
||||
"""
|
||||
if not isinstance(batch_size, int):
|
||||
raise TypeError("batch_size must be an integer")
|
||||
raise TypeError(f"batch_size must be an integer, not {type(batch_size)}")
|
||||
if batch_size < 0:
|
||||
raise ValueError("batch_size must be >= 0")
|
||||
self._check_okay_to_chain()
|
||||
@ -499,7 +499,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
:param skip: the number of results to skip
|
||||
"""
|
||||
if not isinstance(skip, int):
|
||||
raise TypeError("skip must be an integer")
|
||||
raise TypeError(f"skip must be an integer, not {type(skip)}")
|
||||
if skip < 0:
|
||||
raise ValueError("skip must be >= 0")
|
||||
self._check_okay_to_chain()
|
||||
@ -520,7 +520,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
:param max_time_ms: the time limit after which the operation is aborted
|
||||
"""
|
||||
if not isinstance(max_time_ms, int) and max_time_ms is not None:
|
||||
raise TypeError("max_time_ms must be an integer or None")
|
||||
raise TypeError(f"max_time_ms must be an integer or None, not {type(max_time_ms)}")
|
||||
self._check_okay_to_chain()
|
||||
|
||||
self._max_time_ms = max_time_ms
|
||||
@ -543,7 +543,9 @@ class Cursor(Generic[_DocumentType]):
|
||||
.. versionadded:: 3.2
|
||||
"""
|
||||
if not isinstance(max_await_time_ms, int) and max_await_time_ms is not None:
|
||||
raise TypeError("max_await_time_ms must be an integer or None")
|
||||
raise TypeError(
|
||||
f"max_await_time_ms must be an integer or None, not {type(max_await_time_ms)}"
|
||||
)
|
||||
self._check_okay_to_chain()
|
||||
|
||||
# Ignore max_await_time_ms if not tailable or await_data is False.
|
||||
@ -677,7 +679,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
.. versionadded:: 2.7
|
||||
"""
|
||||
if not isinstance(spec, (list, tuple)):
|
||||
raise TypeError("spec must be an instance of list or tuple")
|
||||
raise TypeError(f"spec must be an instance of list or tuple, not {type(spec)}")
|
||||
|
||||
self._check_okay_to_chain()
|
||||
self._max = dict(spec)
|
||||
@ -699,7 +701,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
.. versionadded:: 2.7
|
||||
"""
|
||||
if not isinstance(spec, (list, tuple)):
|
||||
raise TypeError("spec must be an instance of list or tuple")
|
||||
raise TypeError(f"spec must be an instance of list or tuple, not {type(spec)}")
|
||||
|
||||
self._check_okay_to_chain()
|
||||
self._min = dict(spec)
|
||||
|
||||
@ -122,7 +122,7 @@ class Database(common.BaseObject, Generic[_DocumentType]):
|
||||
from pymongo.synchronous.mongo_client import MongoClient
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name must be an instance of str")
|
||||
raise TypeError(f"name must be an instance of str, not {type(name)}")
|
||||
|
||||
if not isinstance(client, MongoClient):
|
||||
# This is for compatibility with mocked and subclassed types, such as in Motor.
|
||||
@ -1303,7 +1303,7 @@ class Database(common.BaseObject, Generic[_DocumentType]):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name_or_collection must be an instance of str")
|
||||
raise TypeError(f"name_or_collection must be an instance of str, not {type(name)}")
|
||||
encrypted_fields = self._get_encrypted_fields(
|
||||
{"encryptedFields": encrypted_fields},
|
||||
name,
|
||||
@ -1367,7 +1367,9 @@ class Database(common.BaseObject, Generic[_DocumentType]):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name_or_collection must be an instance of str or Collection")
|
||||
raise TypeError(
|
||||
f"name_or_collection must be an instance of str or Collection, not {type(name)}"
|
||||
)
|
||||
cmd = {"validate": name, "scandata": scandata, "full": full}
|
||||
if comment is not None:
|
||||
cmd["comment"] = comment
|
||||
|
||||
@ -320,7 +320,9 @@ class _EncryptionIO(MongoCryptCallback): # type: ignore[misc]
|
||||
raw_doc = RawBSONDocument(data_key, _KEY_VAULT_OPTS)
|
||||
data_key_id = raw_doc.get("_id")
|
||||
if not isinstance(data_key_id, Binary) or data_key_id.subtype != UUID_SUBTYPE:
|
||||
raise TypeError("data_key _id must be Binary with a UUID subtype")
|
||||
raise TypeError(
|
||||
f"data_key _id must be Binary with a UUID subtype, not {type(data_key_id)}"
|
||||
)
|
||||
|
||||
assert self.key_vault_coll is not None
|
||||
self.key_vault_coll.insert_one(raw_doc)
|
||||
@ -642,7 +644,9 @@ class ClientEncryption(Generic[_DocumentType]):
|
||||
)
|
||||
|
||||
if not isinstance(codec_options, CodecOptions):
|
||||
raise TypeError("codec_options must be an instance of bson.codec_options.CodecOptions")
|
||||
raise TypeError(
|
||||
f"codec_options must be an instance of bson.codec_options.CodecOptions, not {type(codec_options)}"
|
||||
)
|
||||
|
||||
if not isinstance(key_vault_client, MongoClient):
|
||||
# This is for compatibility with mocked and subclassed types, such as in Motor.
|
||||
|
||||
@ -748,7 +748,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
if port is None:
|
||||
port = self.PORT
|
||||
if not isinstance(port, int):
|
||||
raise TypeError("port must be an instance of int")
|
||||
raise TypeError(f"port must be an instance of int, not {type(port)}")
|
||||
|
||||
# _pool_class, _monitor_class, and _condition_class are for deep
|
||||
# customization of PyMongo, e.g. Motor.
|
||||
@ -1965,7 +1965,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
The cursor is closed synchronously on the current thread.
|
||||
"""
|
||||
if not isinstance(cursor_id, int):
|
||||
raise TypeError("cursor_id must be an instance of int")
|
||||
raise TypeError(f"cursor_id must be an instance of int, not {type(cursor_id)}")
|
||||
|
||||
try:
|
||||
if conn_mgr:
|
||||
@ -2087,7 +2087,9 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
"""If provided session is None, lend a temporary session."""
|
||||
if session is not None:
|
||||
if not isinstance(session, client_session.ClientSession):
|
||||
raise ValueError("'session' argument must be a ClientSession or None.")
|
||||
raise ValueError(
|
||||
f"'session' argument must be a ClientSession or None, not {type(session)}"
|
||||
)
|
||||
# Don't call end_session.
|
||||
yield session
|
||||
return
|
||||
@ -2235,7 +2237,9 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name_or_database must be an instance of str or a Database")
|
||||
raise TypeError(
|
||||
f"name_or_database must be an instance of str or a Database, not {type(name)}"
|
||||
)
|
||||
|
||||
with self._conn_for_writes(session, operation=_Op.DROP_DATABASE) as conn:
|
||||
self[name]._command(
|
||||
|
||||
@ -91,7 +91,7 @@ def parse_userinfo(userinfo: str) -> tuple[str, str]:
|
||||
user, _, passwd = userinfo.partition(":")
|
||||
# No password is expected with GSSAPI authentication.
|
||||
if not user:
|
||||
raise InvalidURI("The empty string is not valid username.")
|
||||
raise InvalidURI("The empty string is not valid username")
|
||||
|
||||
return unquote_plus(user), unquote_plus(passwd)
|
||||
|
||||
@ -347,7 +347,7 @@ def split_options(
|
||||
semi_idx = opts.find(";")
|
||||
try:
|
||||
if and_idx >= 0 and semi_idx >= 0:
|
||||
raise InvalidURI("Can not mix '&' and ';' for option separators.")
|
||||
raise InvalidURI("Can not mix '&' and ';' for option separators")
|
||||
elif and_idx >= 0:
|
||||
options = _parse_options(opts, "&")
|
||||
elif semi_idx >= 0:
|
||||
@ -357,7 +357,7 @@ def split_options(
|
||||
else:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
raise InvalidURI("MongoDB URI options are key=value pairs.") from None
|
||||
raise InvalidURI("MongoDB URI options are key=value pairs") from None
|
||||
|
||||
options = _handle_security_options(options)
|
||||
|
||||
@ -389,7 +389,7 @@ def split_hosts(hosts: str, default_port: Optional[int] = DEFAULT_PORT) -> list[
|
||||
nodes = []
|
||||
for entity in hosts.split(","):
|
||||
if not entity:
|
||||
raise ConfigurationError("Empty host (or extra comma in host list).")
|
||||
raise ConfigurationError("Empty host (or extra comma in host list)")
|
||||
port = default_port
|
||||
# Unix socket entities don't have ports
|
||||
if entity.endswith(".sock"):
|
||||
@ -502,7 +502,7 @@ def parse_uri(
|
||||
raise InvalidURI(f"Invalid URI scheme: URI must begin with '{SCHEME}' or '{SRV_SCHEME}'")
|
||||
|
||||
if not scheme_free:
|
||||
raise InvalidURI("Must provide at least one hostname or IP.")
|
||||
raise InvalidURI("Must provide at least one hostname or IP")
|
||||
|
||||
user = None
|
||||
passwd = None
|
||||
|
||||
@ -74,7 +74,7 @@ class WriteConcern:
|
||||
|
||||
if wtimeout is not None:
|
||||
if not isinstance(wtimeout, int):
|
||||
raise TypeError("wtimeout must be an integer")
|
||||
raise TypeError(f"wtimeout must be an integer, not {type(wtimeout)}")
|
||||
if wtimeout < 0:
|
||||
raise ValueError("wtimeout cannot be less than 0")
|
||||
self.__document["wtimeout"] = wtimeout
|
||||
@ -98,7 +98,7 @@ class WriteConcern:
|
||||
raise ValueError("w cannot be less than 0")
|
||||
self.__acknowledged = w > 0
|
||||
elif not isinstance(w, str):
|
||||
raise TypeError("w must be an integer or string")
|
||||
raise TypeError(f"w must be an integer or string, not {type(w)}")
|
||||
self.__document["w"] = w
|
||||
|
||||
self.__server_default = not self.__document
|
||||
|
||||
Loading…
Reference in New Issue
Block a user