diff --git a/bson/__init__.py b/bson/__init__.py index 343fbecb2..11a87bbe7 100644 --- a/bson/__init__.py +++ b/bson/__init__.py @@ -76,6 +76,7 @@ from typing import ( List, Mapping, MutableMapping, + NoReturn, Optional, Sequence, Tuple, @@ -170,7 +171,7 @@ def get_data_and_view(data: Any) -> Tuple[Any, memoryview]: return view.tobytes(), view -def _raise_unknown_type(element_type: int, element_name: str) -> None: +def _raise_unknown_type(element_type: int, element_name: str) -> NoReturn: """Unknown type helper.""" raise InvalidBSON( "Detected unknown BSON type %r for fieldname '%s'. Are " diff --git a/bson/objectid.py b/bson/objectid.py index 24d25d037..c174b4732 100644 --- a/bson/objectid.py +++ b/bson/objectid.py @@ -24,7 +24,7 @@ import struct import threading import time from random import SystemRandom -from typing import Any, Optional, Type, Union +from typing import Any, NoReturn, Optional, Type, Union from bson.errors import InvalidId from bson.tz_util import utc @@ -32,7 +32,7 @@ from bson.tz_util import utc _MAX_COUNTER_VALUE = 0xFFFFFF -def _raise_invalid_id(oid: str) -> None: +def _raise_invalid_id(oid: str) -> NoReturn: raise InvalidId( "%r is not a valid ObjectId, it must be a 12-byte input" " or a 24-character hex string" % oid diff --git a/gridfs/grid_file.py b/gridfs/grid_file.py index b290fc68b..5d63d5c65 100644 --- a/gridfs/grid_file.py +++ b/gridfs/grid_file.py @@ -17,7 +17,7 @@ import datetime import io import math import os -from typing import Any, Iterable, List, Mapping, Optional +from typing import Any, Iterable, List, Mapping, NoReturn, Optional from bson.binary import Binary from bson.int64 import Int64 @@ -298,7 +298,7 @@ class GridIn(object): except DuplicateKeyError: self._raise_file_exists(self._id) - def _raise_file_exists(self, file_id: Any) -> None: + def _raise_file_exists(self, file_id: Any) -> NoReturn: """Raise a FileExists exception for the given file_id.""" raise FileExists("file with _id %r already exists" % file_id) @@ -312,7 +312,7 @@ class GridIn(object): self.__flush() object.__setattr__(self, "_closed", True) - def read(self, size: Optional[int] = -1) -> None: + def read(self, size: int = -1) -> NoReturn: raise io.UnsupportedOperation("read") def readable(self) -> bool: @@ -682,10 +682,10 @@ class GridOut(io.IOBase): self.__chunk_iter = None super().close() - def write(self, value: Any) -> None: + def write(self, value: Any) -> NoReturn: raise io.UnsupportedOperation("write") - def writelines(self, lines: Any) -> None: + def writelines(self, lines: Any) -> NoReturn: raise io.UnsupportedOperation("writelines") def writable(self) -> bool: @@ -704,7 +704,7 @@ class GridOut(io.IOBase): self.close() return False - def fileno(self) -> int: + def fileno(self) -> NoReturn: raise io.UnsupportedOperation("fileno") def flush(self) -> None: @@ -714,7 +714,7 @@ class GridOut(io.IOBase): def isatty(self) -> bool: return False - def truncate(self, size: Optional[int] = None) -> int: + def truncate(self, size: Optional[int] = None) -> NoReturn: # See https://docs.python.org/3/library/io.html#io.IOBase.writable # for why truncate has to raise. raise io.UnsupportedOperation("truncate") @@ -891,10 +891,10 @@ class GridOutCursor(Cursor): __next__ = next - def add_option(self, *args: Any, **kwargs: Any) -> None: # type: ignore[override] + def add_option(self, *args: Any, **kwargs: Any) -> NoReturn: raise NotImplementedError("Method does not exist for GridOutCursor") - def remove_option(self, *args: Any, **kwargs: Any) -> None: # type: ignore[override] + def remove_option(self, *args: Any, **kwargs: Any) -> NoReturn: raise NotImplementedError("Method does not exist for GridOutCursor") def _clone_base(self, session: ClientSession) -> "GridOutCursor": diff --git a/pymongo/bulk.py b/pymongo/bulk.py index 9055e40e9..44923f73d 100644 --- a/pymongo/bulk.py +++ b/pymongo/bulk.py @@ -18,6 +18,7 @@ """ import copy from itertools import islice +from typing import Any, NoReturn from bson.objectid import ObjectId from bson.raw_bson import RawBSONDocument @@ -128,7 +129,7 @@ def _merge_command(run, full_result, offset, result): full_result["writeConcernErrors"].append(wce) -def _raise_bulk_write_error(full_result): +def _raise_bulk_write_error(full_result: Any) -> NoReturn: """Raise a BulkWriteError from the full bulk api result.""" if full_result["writeErrors"]: full_result["writeErrors"].sort(key=lambda error: error["index"]) diff --git a/pymongo/client_session.py b/pymongo/client_session.py index 20d36fb06..a0c269cb8 100644 --- a/pymongo/client_session.py +++ b/pymongo/client_session.py @@ -142,6 +142,7 @@ from typing import ( ContextManager, Generic, Mapping, + NoReturn, Optional, TypeVar, ) @@ -422,7 +423,7 @@ class _Transaction(object): self.sock_mgr = None -def _reraise_with_unknown_commit(exc): +def _reraise_with_unknown_commit(exc: Any) -> NoReturn: """Re-raise an exception with the UnknownTransactionCommitResult label.""" exc._add_error_label("UnknownTransactionCommitResult") raise @@ -1003,7 +1004,7 @@ class ClientSession(Generic[_DocumentType]): if self._snapshot_time is not None: rc["atClusterTime"] = self._snapshot_time - def __copy__(self): + def __copy__(self) -> NoReturn: raise TypeError("A ClientSession cannot be copied, create a new session instead") diff --git a/pymongo/collection.py b/pymongo/collection.py index dc344b640..d0ebd9311 100644 --- a/pymongo/collection.py +++ b/pymongo/collection.py @@ -23,6 +23,7 @@ from typing import ( List, Mapping, MutableMapping, + NoReturn, Optional, Sequence, Tuple, @@ -343,7 +344,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]): def __hash__(self) -> int: return hash((self.__database, self.__name)) - def __bool__(self) -> bool: + def __bool__(self) -> NoReturn: raise NotImplementedError( "Collection objects do not implement truth " "value testing or bool(). Please compare " @@ -3143,12 +3144,12 @@ class Collection(common.BaseObject, Generic[_DocumentType]): def __iter__(self) -> "Collection[_DocumentType]": return self - def __next__(self) -> None: + def __next__(self) -> NoReturn: raise TypeError("'Collection' object is not iterable") next = __next__ - def __call__(self, *args: Any, **kwargs: Any) -> None: + def __call__(self, *args: Any, **kwargs: Any) -> NoReturn: """This is only here so that some API misusages are easier to debug.""" if "." not in self.__name: raise TypeError( diff --git a/pymongo/command_cursor.py b/pymongo/command_cursor.py index d10e23f95..0bd99f0bb 100644 --- a/pymongo/command_cursor.py +++ b/pymongo/command_cursor.py @@ -15,7 +15,7 @@ """CommandCursor class to iterate over command results.""" from collections import deque -from typing import TYPE_CHECKING, Any, Generic, Iterator, Mapping, Optional +from typing import TYPE_CHECKING, Any, Generic, Iterator, Mapping, NoReturn, Optional from bson import _convert_raw_document_lists_to_streams from pymongo.cursor import _CURSOR_CLOSED_ERRORS, _SocketManager @@ -344,5 +344,5 @@ class RawBatchCommandCursor(CommandCursor, Generic[_DocumentType]): _convert_raw_document_lists_to_streams(raw_response[0]) return raw_response - def __getitem__(self, index): + def __getitem__(self, index: int) -> NoReturn: raise InvalidOperation("Cannot call __getitem__ on RawBatchCursor") diff --git a/pymongo/common.py b/pymongo/common.py index 5255468b5..669e12ead 100644 --- a/pymongo/common.py +++ b/pymongo/common.py @@ -25,6 +25,7 @@ from typing import ( List, Mapping, MutableMapping, + NoReturn, Optional, Sequence, Tuple, @@ -153,7 +154,7 @@ def clean_node(node: str) -> Tuple[str, int]: return host.lower(), port -def raise_config_error(key: str, dummy: Any) -> None: +def raise_config_error(key: str, dummy: Any) -> NoReturn: """Raise ConfigurationError with the given key name.""" raise ConfigurationError("Unknown option %s" % (key,)) diff --git a/pymongo/cursor.py b/pymongo/cursor.py index a2ccdf586..9f6f0898b 100644 --- a/pymongo/cursor.py +++ b/pymongo/cursor.py @@ -25,6 +25,7 @@ from typing import ( Iterable, List, Mapping, + NoReturn, Optional, Sequence, Tuple, @@ -1339,5 +1340,5 @@ class RawBatchCursor(Cursor, Generic[_DocumentType]): clone = self._clone(deepcopy=True, base=Cursor(self.collection)) return clone.explain() - def __getitem__(self, index: Any) -> "Cursor[_DocumentType]": + def __getitem__(self, index: Any) -> NoReturn: raise InvalidOperation("Cannot call __getitem__ on RawBatchCursor") diff --git a/pymongo/database.py b/pymongo/database.py index 6f2d0fd5c..17cba06b6 100644 --- a/pymongo/database.py +++ b/pymongo/database.py @@ -21,6 +21,7 @@ from typing import ( List, Mapping, MutableMapping, + NoReturn, Optional, Sequence, TypeVar, @@ -1010,12 +1011,12 @@ class Database(common.BaseObject, Generic[_DocumentType]): def __iter__(self) -> "Database[_DocumentType]": return self - def __next__(self) -> "Database[_DocumentType]": + def __next__(self) -> NoReturn: raise TypeError("'Database' object is not iterable") next = __next__ - def __bool__(self) -> bool: + def __bool__(self) -> NoReturn: raise NotImplementedError( "Database objects do not implement truth " "value testing or bool(). Please compare " diff --git a/pymongo/helpers.py b/pymongo/helpers.py index 8311aafa8..60b69424a 100644 --- a/pymongo/helpers.py +++ b/pymongo/helpers.py @@ -17,7 +17,7 @@ import sys import traceback from collections import abc -from typing import Any +from typing import Any, List, NoReturn from bson.son import SON from pymongo import ASCENDING @@ -180,7 +180,7 @@ def _check_command_response( raise OperationFailure(errmsg, code, response, max_wire_version) -def _raise_last_write_error(write_errors): +def _raise_last_write_error(write_errors: List[Any]) -> NoReturn: # If the last batch had multiple errors only report # the last error to emulate continue_on_error. error = write_errors[-1] @@ -189,7 +189,7 @@ def _raise_last_write_error(write_errors): raise WriteError(error.get("errmsg"), error.get("code"), error) -def _raise_write_concern_error(error): +def _raise_write_concern_error(error: Any) -> NoReturn: if "errInfo" in error and error["errInfo"].get("wtimeout"): # Make sure we raise WTimeoutError raise WTimeoutError(error.get("errmsg"), error.get("code"), error) diff --git a/pymongo/message.py b/pymongo/message.py index 58f71629d..6aa8e4e7f 100644 --- a/pymongo/message.py +++ b/pymongo/message.py @@ -24,7 +24,7 @@ import datetime import random import struct from io import BytesIO as _BytesIO -from typing import Any, Dict +from typing import Any, Dict, NoReturn import bson from bson import CodecOptions, _decode_selective, _dict_to_bson, _make_c_string, encode @@ -991,7 +991,7 @@ class _EncryptedBulkWriteContext(_BulkWriteContext): return _MAX_SPLIT_SIZE_ENC -def _raise_document_too_large(operation, doc_size, max_size): +def _raise_document_too_large(operation: str, doc_size: int, max_size: int) -> NoReturn: """Internal helper for raising DocumentTooLarge.""" if operation == "insert": raise DocumentTooLarge( diff --git a/pymongo/mongo_client.py b/pymongo/mongo_client.py index 4231db95a..280818ce0 100644 --- a/pymongo/mongo_client.py +++ b/pymongo/mongo_client.py @@ -43,6 +43,7 @@ from typing import ( Generic, List, Mapping, + NoReturn, Optional, Sequence, Set, @@ -1975,7 +1976,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]): def __iter__(self) -> "MongoClient[_DocumentType]": return self - def __next__(self) -> None: + def __next__(self) -> NoReturn: raise TypeError("'MongoClient' object is not iterable") next = __next__ diff --git a/pymongo/pool.py b/pymongo/pool.py index c7bd21fc8..1aaae4067 100644 --- a/pymongo/pool.py +++ b/pymongo/pool.py @@ -24,7 +24,7 @@ import sys import threading import time import weakref -from typing import Any +from typing import Any, NoReturn, Optional from bson import DEFAULT_CODEC_OPTIONS from bson.son import SON @@ -249,7 +249,9 @@ else: "foo".encode("idna") -def _raise_connection_failure(address, error, msg_prefix=None): +def _raise_connection_failure( + address: Any, error: Exception, msg_prefix: Optional[str] = None +) -> NoReturn: """Convert a socket.error to ConnectionFailure and raise it.""" host, port = address # If connecting to a Unix socket, port will be None. @@ -1593,7 +1595,7 @@ class Pool: return False - def _raise_wait_queue_timeout(self): + def _raise_wait_queue_timeout(self) -> NoReturn: listeners = self.opts._event_listeners if self.enabled_for_cmap: listeners.publish_connection_check_out_failed(