diff --git a/.gitignore b/.gitignore index 56f842e1..62bd6e89 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ __pycache__/ *.egg-info/ .pytest_cache/ .mypy_cache/ +.ruff_cache/ dist/ dist-doc/ build/ diff --git a/client/pyproject.toml b/client/pyproject.toml index 613ddf22..f6e3875f 100644 --- a/client/pyproject.toml +++ b/client/pyproject.toml @@ -28,10 +28,8 @@ dynamic = ["version"] [project.optional-dependencies] cryptg = ["cryptg~=0.4"] dev = [ - "isort~=5.12", - "black~=23.3.0", - "mypy~=1.3", - "ruff~=0.0.292", + "mypy~=1.11.2", + "ruff~=0.6.8", "pytest~=7.3", "pytest-asyncio~=0.21", ] @@ -55,6 +53,13 @@ backend-path = ["build_backend"] version = {attr = "telethon.version.__version__"} [tool.ruff] +exclude = ["doc"] + +[tool.ruff.lint] +select = ["F", "E", "W", "I", "N", "ANN"] ignore = [ "E501", # formatter takes care of lines that are too long besides documentation + "ANN101", # Missing type annotation for `self` in method + "ANN102", # Missing type annotation for `cls` in classmethod + "ANN401", # Dynamically typed expressions (typing.Any) are not type checked ] diff --git a/client/src/telethon/_impl/client/client/bots.py b/client/src/telethon/_impl/client/client/bots.py index 10aa79d8..f8de14fc 100644 --- a/client/src/telethon/_impl/client/client/bots.py +++ b/client/src/telethon/_impl/client/client/bots.py @@ -18,7 +18,7 @@ class InlineResults(metaclass=NoPublicConstructor): bot: abcs.InputUser, query: str, peer: Optional[PeerRef], - ): + ) -> None: self._client = client self._bot = bot self._query = query diff --git a/client/src/telethon/_impl/client/client/chats.py b/client/src/telethon/_impl/client/client/chats.py index 9c507709..8dd9de0d 100644 --- a/client/src/telethon/_impl/client/client/chats.py +++ b/client/src/telethon/_impl/client/client/chats.py @@ -29,7 +29,7 @@ class ParticipantList(AsyncList[Participant]): self, client: Client, peer: ChannelRef | GroupRef, - ): + ) -> None: super().__init__() self._client = client self._peer = peer @@ -106,7 +106,7 @@ class RecentActionList(AsyncList[RecentAction]): self, client: Client, peer: ChannelRef | GroupRef, - ): + ) -> None: super().__init__() self._client = client self._peer = peer @@ -148,7 +148,7 @@ class ProfilePhotoList(AsyncList[File]): self, client: Client, peer: PeerRef, - ): + ) -> None: super().__init__() self._client = client self._peer = peer diff --git a/client/src/telethon/_impl/client/client/dialogs.py b/client/src/telethon/_impl/client/client/dialogs.py index 2b3cf9f3..65711063 100644 --- a/client/src/telethon/_impl/client/client/dialogs.py +++ b/client/src/telethon/_impl/client/client/dialogs.py @@ -20,7 +20,7 @@ if TYPE_CHECKING: class DialogList(AsyncList[Dialog]): - def __init__(self, client: Client): + def __init__(self, client: Client) -> None: super().__init__() self._client = client self._offset = 0 @@ -93,7 +93,7 @@ async def delete_dialog(self: Client, dialog: Peer | PeerRef, /) -> None: class DraftList(AsyncList[Draft]): - def __init__(self, client: Client): + def __init__(self, client: Client) -> None: super().__init__() self._client = client self._offset = 0 diff --git a/client/src/telethon/_impl/client/client/files.py b/client/src/telethon/_impl/client/client/files.py index a0ec66ed..0de07c96 100644 --- a/client/src/telethon/_impl/client/client/files.py +++ b/client/src/telethon/_impl/client/client/files.py @@ -425,7 +425,7 @@ class FileBytesList(AsyncList[bytes]): self, client: Client, file: File, - ): + ) -> None: super().__init__() self._client = client self._loc = file._input_location() diff --git a/client/src/telethon/_impl/client/client/messages.py b/client/src/telethon/_impl/client/client/messages.py index 23f038a9..e19aee63 100644 --- a/client/src/telethon/_impl/client/client/messages.py +++ b/client/src/telethon/_impl/client/client/messages.py @@ -253,7 +253,7 @@ class HistoryList(MessageList): *, offset_id: int, offset_date: int, - ): + ) -> None: super().__init__() self._client = client self._peer = peer @@ -323,7 +323,7 @@ class CherryPickedList(MessageList): client: Client, peer: PeerRef, ids: list[int], - ): + ) -> None: super().__init__() self._client = client self._peer = peer @@ -367,7 +367,7 @@ class SearchList(MessageList): query: str, offset_id: int, offset_date: int, - ): + ) -> None: super().__init__() self._client = client self._peer = peer @@ -434,7 +434,7 @@ class GlobalSearchList(MessageList): query: str, offset_id: int, offset_date: int, - ): + ) -> None: super().__init__() self._client = client self._limit = limit diff --git a/client/src/telethon/_impl/client/client/net.py b/client/src/telethon/_impl/client/client/net.py index 23634cdb..8fcaf1bb 100644 --- a/client/src/telethon/_impl/client/client/net.py +++ b/client/src/telethon/_impl/client/client/net.py @@ -9,7 +9,7 @@ from dataclasses import dataclass, field from typing import TYPE_CHECKING, Optional, TypeVar from ....version import __version__ -from ...mtproto import BadStatus, Full, RpcError +from ...mtproto import BadStatusError, Full, RpcError from ...mtsender import Connector, Sender from ...mtsender import connect as do_connect_sender from ...session import DataCenter @@ -120,7 +120,7 @@ async def connect_sender( ), ) ) - except BadStatus as e: + except BadStatusError as e: if e.status == 404 and auth: dc = DataCenter( id=dc.id, ipv4_addr=dc.ipv4_addr, ipv6_addr=dc.ipv6_addr, auth=None diff --git a/client/src/telethon/_impl/client/client/updates.py b/client/src/telethon/_impl/client/client/updates.py index 2ef036a4..aa12a6d6 100644 --- a/client/src/telethon/_impl/client/client/updates.py +++ b/client/src/telethon/_impl/client/client/updates.py @@ -5,7 +5,7 @@ from collections.abc import Awaitable, Callable from inspect import isawaitable from typing import TYPE_CHECKING, Any, Optional, Sequence, Type -from ...session import Gap +from ...session import GapError from ...tl import abcs from ..events import Continue, Event from ..events.filters import FilterType @@ -80,14 +80,14 @@ def process_socket_updates(client: Client, all_updates: list[abcs.Updates]) -> N for updates in all_updates: try: client._message_box.ensure_known_peer_hashes(updates, client._chat_hashes) - except Gap: + except GapError: return try: result, users, chats = client._message_box.process_updates( updates, client._chat_hashes ) - except Gap: + except GapError: return extend_update_queue(client, result, users, chats) diff --git a/client/src/telethon/_impl/client/client/users.py b/client/src/telethon/_impl/client/client/users.py index 345f05d7..96e0027d 100644 --- a/client/src/telethon/_impl/client/client/users.py +++ b/client/src/telethon/_impl/client/client/users.py @@ -25,7 +25,7 @@ async def get_me(self: Client) -> Optional[User]: class ContactList(AsyncList[User]): - def __init__(self, client: Client): + def __init__(self, client: Client) -> None: super().__init__() self._client = client diff --git a/client/src/telethon/_impl/client/events/event.py b/client/src/telethon/_impl/client/events/event.py index 8fcc2dbf..3fae19ec 100644 --- a/client/src/telethon/_impl/client/events/event.py +++ b/client/src/telethon/_impl/client/events/event.py @@ -46,7 +46,7 @@ class Raw(Event): client: Client, update: abcs.Update, chat_map: dict[int, Peer], - ): + ) -> None: self._client = client self._raw = update self._chat_map = chat_map diff --git a/client/src/telethon/_impl/client/events/queries.py b/client/src/telethon/_impl/client/events/queries.py index 276c35c6..3736d9a4 100644 --- a/client/src/telethon/_impl/client/events/queries.py +++ b/client/src/telethon/_impl/client/events/queries.py @@ -25,7 +25,7 @@ class ButtonCallback(Event): client: Client, update: types.UpdateBotCallbackQuery, chat_map: dict[int, Peer], - ): + ) -> None: self._client = client self._raw = update self._chat_map = chat_map @@ -101,7 +101,7 @@ class InlineQuery(Event): Only bot accounts can receive this event. """ - def __init__(self, update: types.UpdateBotInlineQuery): + def __init__(self, update: types.UpdateBotInlineQuery) -> None: self._raw = update @classmethod diff --git a/client/src/telethon/_impl/client/parsers/html.py b/client/src/telethon/_impl/client/parsers/html.py index cafa3d3d..6958583f 100644 --- a/client/src/telethon/_impl/client/parsers/html.py +++ b/client/src/telethon/_impl/client/parsers/html.py @@ -36,20 +36,20 @@ class HTMLToTelegramParser(HTMLParser): self._open_tags_meta.appendleft(None) attributes = dict(attrs) - EntityType: Optional[Type[MessageEntity]] = None + entity_type: Optional[Type[MessageEntity]] = None args = {} if tag == "strong" or tag == "b": - EntityType = MessageEntityBold + entity_type = MessageEntityBold elif tag == "em" or tag == "i": - EntityType = MessageEntityItalic + entity_type = MessageEntityItalic elif tag == "u": - EntityType = MessageEntityUnderline + entity_type = MessageEntityUnderline elif tag == "del" or tag == "s": - EntityType = MessageEntityStrike + entity_type = MessageEntityStrike elif tag == "blockquote": - EntityType = MessageEntityBlockquote + entity_type = MessageEntityBlockquote elif tag == "details": - EntityType = MessageEntitySpoiler + entity_type = MessageEntitySpoiler elif tag == "code": try: # If we're in the middle of a
 tag, this  tag is
@@ -63,9 +63,9 @@ class HTMLToTelegramParser(HTMLParser):
                 if cls := attributes.get("class"):
                     pre.language = cls[len("language-") :]
             except KeyError:
-                EntityType = MessageEntityCode
+                entity_type = MessageEntityCode
         elif tag == "pre":
-            EntityType = MessageEntityPre
+            entity_type = MessageEntityPre
             args["language"] = ""
         elif tag == "a":
             url = attributes.get("href")
@@ -73,20 +73,20 @@ class HTMLToTelegramParser(HTMLParser):
                 return
             if url.startswith("mailto:"):
                 url = url[len("mailto:") :]
-                EntityType = MessageEntityEmail
+                entity_type = MessageEntityEmail
             else:
                 if self.get_starttag_text() == url:
-                    EntityType = MessageEntityUrl
+                    entity_type = MessageEntityUrl
                 else:
-                    EntityType = MessageEntityTextUrl
+                    entity_type = MessageEntityTextUrl
                     args["url"] = del_surrogate(url)
                     url = None
             self._open_tags_meta.popleft()
             self._open_tags_meta.appendleft(url)
 
-        if EntityType and tag not in self._building_entities:
-            Et = cast(Any, EntityType)
-            self._building_entities[tag] = Et(
+        if entity_type and tag not in self._building_entities:
+            any_entity_type = cast(Any, entity_type)
+            self._building_entities[tag] = any_entity_type(
                 offset=len(self.text),
                 # The length will be determined when closing the tag.
                 length=0,
diff --git a/client/src/telethon/_impl/client/types/album_builder.py b/client/src/telethon/_impl/client/types/album_builder.py
index 5ead413f..8b0f8c9d 100644
--- a/client/src/telethon/_impl/client/types/album_builder.py
+++ b/client/src/telethon/_impl/client/types/album_builder.py
@@ -22,7 +22,7 @@ class AlbumBuilder(metaclass=NoPublicConstructor):
     This class is constructed by calling :meth:`telethon.Client.prepare_album`.
     """
 
-    def __init__(self, *, client: Client):
+    def __init__(self, *, client: Client) -> None:
         self._client = client
         self._medias: list[types.InputSingleMedia] = []
 
diff --git a/client/src/telethon/_impl/client/types/file.py b/client/src/telethon/_impl/client/types/file.py
index 1e5e018f..566e4aa4 100644
--- a/client/src/telethon/_impl/client/types/file.py
+++ b/client/src/telethon/_impl/client/types/file.py
@@ -122,7 +122,7 @@ class OutWrapper:
     _fd: OutFileLike | BufferedWriter
     _owned_fd: Optional[BufferedWriter]
 
-    def __init__(self, file: str | Path | OutFileLike):
+    def __init__(self, file: str | Path | OutFileLike) -> None:
         if isinstance(file, str):
             file = Path(file)
 
@@ -166,7 +166,7 @@ class File(metaclass=NoPublicConstructor):
         thumbs: Optional[Sequence[abcs.PhotoSize]],
         raw: Optional[abcs.MessageMedia | abcs.Photo | abcs.Document],
         client: Optional[Client],
-    ):
+    ) -> None:
         self._attributes = attributes
         self._size = size
         self._name = name
diff --git a/client/src/telethon/_impl/client/types/inline_result.py b/client/src/telethon/_impl/client/types/inline_result.py
index 86cfb34e..a32e6a82 100644
--- a/client/src/telethon/_impl/client/types/inline_result.py
+++ b/client/src/telethon/_impl/client/types/inline_result.py
@@ -25,7 +25,7 @@ class InlineResult(metaclass=NoPublicConstructor):
         results: types.messages.BotResults,
         result: types.BotInlineMediaResult | types.BotInlineResult,
         default_peer: Optional[PeerRef],
-    ):
+    ) -> None:
         self._client = client
         self._raw_results = results
         self._raw = result
diff --git a/client/src/telethon/_impl/crypto/aes.py b/client/src/telethon/_impl/crypto/aes.py
index 60e74964..bc248801 100644
--- a/client/src/telethon/_impl/crypto/aes.py
+++ b/client/src/telethon/_impl/crypto/aes.py
@@ -1,5 +1,5 @@
 try:
-    import cryptg
+    import cryptg  # type: ignore [import-untyped]
 
     def ige_encrypt(
         plaintext: bytes | bytearray | memoryview, key: bytes, iv: bytes
@@ -18,7 +18,7 @@ try:
         )
 
 except ImportError:
-    import pyaes
+    import pyaes  # type: ignore [import-untyped]
 
     def ige_encrypt(
         plaintext: bytes | bytearray | memoryview, key: bytes, iv: bytes
diff --git a/client/src/telethon/_impl/mtproto/__init__.py b/client/src/telethon/_impl/mtproto/__init__.py
index d0ff7b43..2291bb2b 100644
--- a/client/src/telethon/_impl/mtproto/__init__.py
+++ b/client/src/telethon/_impl/mtproto/__init__.py
@@ -3,7 +3,7 @@ from .authentication import step1 as auth_step1
 from .authentication import step2 as auth_step2
 from .authentication import step3 as auth_step3
 from .mtp import (
-    BadMessage,
+    BadMessageError,
     Deserialization,
     Encrypted,
     MsgId,
@@ -13,7 +13,14 @@ from .mtp import (
     RpcResult,
     Update,
 )
-from .transport import Abridged, BadStatus, Full, Intermediate, MissingBytes, Transport
+from .transport import (
+    Abridged,
+    BadStatusError,
+    Full,
+    Intermediate,
+    MissingBytesError,
+    Transport,
+)
 from .utils import DEFAULT_COMPRESSION_THRESHOLD
 
 __all__ = [
@@ -25,7 +32,7 @@ __all__ = [
     "auth_step1",
     "auth_step2",
     "auth_step3",
-    "BadMessage",
+    "BadMessageError",
     "Deserialization",
     "Encrypted",
     "MsgId",
@@ -35,10 +42,10 @@ __all__ = [
     "RpcResult",
     "Update",
     "Abridged",
-    "BadStatus",
+    "BadStatusError",
     "Full",
     "Intermediate",
-    "MissingBytes",
+    "MissingBytesError",
     "Transport",
     "DEFAULT_COMPRESSION_THRESHOLD",
 ]
diff --git a/client/src/telethon/_impl/mtproto/authentication.py b/client/src/telethon/_impl/mtproto/authentication.py
index 1b20dc47..c38b26dc 100644
--- a/client/src/telethon/_impl/mtproto/authentication.py
+++ b/client/src/telethon/_impl/mtproto/authentication.py
@@ -310,4 +310,4 @@ def check_new_nonce_hash(got: int, expected: int) -> None:
 
 def check_g_in_range(value: int, low: int, high: int) -> None:
     if not (low < value < high):
-        raise ValueError(f"g parameter {value} not in range({low+1}, {high})")
+        raise ValueError(f"g parameter {value} not in range({low + 1}, {high})")
diff --git a/client/src/telethon/_impl/mtproto/mtp/__init__.py b/client/src/telethon/_impl/mtproto/mtp/__init__.py
index 4f572684..c38d4d93 100644
--- a/client/src/telethon/_impl/mtproto/mtp/__init__.py
+++ b/client/src/telethon/_impl/mtproto/mtp/__init__.py
@@ -1,11 +1,19 @@
 from .encrypted import Encrypted
 from .plain import Plain
-from .types import BadMessage, Deserialization, MsgId, Mtp, RpcError, RpcResult, Update
+from .types import (
+    BadMessageError,
+    Deserialization,
+    MsgId,
+    Mtp,
+    RpcError,
+    RpcResult,
+    Update,
+)
 
 __all__ = [
     "Encrypted",
     "Plain",
-    "BadMessage",
+    "BadMessageError",
     "Deserialization",
     "MsgId",
     "Mtp",
diff --git a/client/src/telethon/_impl/mtproto/mtp/encrypted.py b/client/src/telethon/_impl/mtproto/mtp/encrypted.py
index 5195b950..abcb7015 100644
--- a/client/src/telethon/_impl/mtproto/mtp/encrypted.py
+++ b/client/src/telethon/_impl/mtproto/mtp/encrypted.py
@@ -60,7 +60,15 @@ from ..utils import (
     gzip_decompress,
     message_requires_ack,
 )
-from .types import BadMessage, Deserialization, MsgId, Mtp, RpcError, RpcResult, Update
+from .types import (
+    BadMessageError,
+    Deserialization,
+    MsgId,
+    Mtp,
+    RpcError,
+    RpcResult,
+    Update,
+)
 
 NUM_FUTURE_SALTS = 64
 
@@ -269,7 +277,7 @@ class Encrypted(Mtp):
         bad_msg = AbcBadMsgNotification.from_bytes(message.body)
         assert isinstance(bad_msg, (BadServerSalt, BadMsgNotification))
 
-        exc = BadMessage(msg_id=MsgId(bad_msg.bad_msg_id), code=bad_msg.error_code)
+        exc = BadMessageError(msg_id=MsgId(bad_msg.bad_msg_id), code=bad_msg.error_code)
 
         if bad_msg.bad_msg_id == self._salt_request_msg_id:
             # Response to internal request, do not propagate.
diff --git a/client/src/telethon/_impl/mtproto/mtp/types.py b/client/src/telethon/_impl/mtproto/mtp/types.py
index 3798d859..0dc23378 100644
--- a/client/src/telethon/_impl/mtproto/mtp/types.py
+++ b/client/src/telethon/_impl/mtproto/mtp/types.py
@@ -15,7 +15,7 @@ class Update:
 
     __slots__ = ("body",)
 
-    def __init__(self, body: bytes | bytearray | memoryview):
+    def __init__(self, body: bytes | bytearray | memoryview) -> None:
         self.body = body
 
 
@@ -26,7 +26,7 @@ class RpcResult:
 
     __slots__ = ("msg_id", "body")
 
-    def __init__(self, msg_id: MsgId, body: bytes | bytearray | memoryview):
+    def __init__(self, msg_id: MsgId, body: bytes | bytearray | memoryview) -> None:
         self.msg_id = msg_id
         self.body = body
 
@@ -142,7 +142,7 @@ RETRYABLE_MSG_IDS = {16, 17, 48}
 NON_FATAL_MSG_IDS = RETRYABLE_MSG_IDS & {32, 33}
 
 
-class BadMessage(ValueError):
+class BadMessageError(ValueError):
     def __init__(
         self,
         *args: object,
@@ -178,7 +178,7 @@ class BadMessage(ValueError):
         return self._code == other._code
 
 
-Deserialization = Update | RpcResult | RpcError | BadMessage
+Deserialization = Update | RpcResult | RpcError | BadMessageError
 
 
 # https://core.telegram.org/mtproto/description
diff --git a/client/src/telethon/_impl/mtproto/transport/__init__.py b/client/src/telethon/_impl/mtproto/transport/__init__.py
index 50979449..8c537688 100644
--- a/client/src/telethon/_impl/mtproto/transport/__init__.py
+++ b/client/src/telethon/_impl/mtproto/transport/__init__.py
@@ -1,6 +1,13 @@
-from .abcs import BadStatus, MissingBytes, Transport
+from .abcs import BadStatusError, MissingBytesError, Transport
 from .abridged import Abridged
 from .full import Full
 from .intermediate import Intermediate
 
-__all__ = ["BadStatus", "MissingBytes", "Transport", "Abridged", "Full", "Intermediate"]
+__all__ = [
+    "BadStatusError",
+    "MissingBytesError",
+    "Transport",
+    "Abridged",
+    "Full",
+    "Intermediate",
+]
diff --git a/client/src/telethon/_impl/mtproto/transport/abcs.py b/client/src/telethon/_impl/mtproto/transport/abcs.py
index 149dc6ee..d1b01956 100644
--- a/client/src/telethon/_impl/mtproto/transport/abcs.py
+++ b/client/src/telethon/_impl/mtproto/transport/abcs.py
@@ -16,12 +16,12 @@ class Transport(ABC):
         pass
 
 
-class MissingBytes(ValueError):
+class MissingBytesError(ValueError):
     def __init__(self, *, expected: int, got: int) -> None:
         super().__init__(f"missing bytes, expected: {expected}, got: {got}")
 
 
-class BadStatus(ValueError):
+class BadStatusError(ValueError):
     def __init__(self, *, status: int) -> None:
         super().__init__(f"transport reported bad status: {status}")
         self.status = status
diff --git a/client/src/telethon/_impl/mtproto/transport/abridged.py b/client/src/telethon/_impl/mtproto/transport/abridged.py
index 85a152b6..1f8cf482 100644
--- a/client/src/telethon/_impl/mtproto/transport/abridged.py
+++ b/client/src/telethon/_impl/mtproto/transport/abridged.py
@@ -1,6 +1,6 @@
 import struct
 
-from .abcs import BadStatus, MissingBytes, OutFn, Transport
+from .abcs import BadStatusError, MissingBytesError, OutFn, Transport
 
 
 class Abridged(Transport):
@@ -38,25 +38,25 @@ class Abridged(Transport):
 
     def unpack(self, input: bytes | bytearray | memoryview, output: bytearray) -> int:
         if not input:
-            raise MissingBytes(expected=1, got=0)
+            raise MissingBytesError(expected=1, got=0)
 
         length = input[0]
         if 1 < length < 127:
             header_len = 1
         elif len(input) < 4:
-            raise MissingBytes(expected=4, got=len(input))
+            raise MissingBytesError(expected=4, got=len(input))
         else:
             header_len = 4
             length = struct.unpack_from("> 8
 
         if length <= 0:
             if length < 0:
-                raise BadStatus(status=-length)
+                raise BadStatusError(status=-length)
             raise ValueError(f"bad length, expected > 0, got: {length}")
 
         length *= 4
         if len(input) < header_len + length:
-            raise MissingBytes(expected=header_len + length, got=len(input))
+            raise MissingBytesError(expected=header_len + length, got=len(input))
 
         output += memoryview(input)[header_len : header_len + length]
         return header_len + length
diff --git a/client/src/telethon/_impl/mtproto/transport/full.py b/client/src/telethon/_impl/mtproto/transport/full.py
index bd40b523..59cc1e2c 100644
--- a/client/src/telethon/_impl/mtproto/transport/full.py
+++ b/client/src/telethon/_impl/mtproto/transport/full.py
@@ -1,7 +1,7 @@
 import struct
 from zlib import crc32
 
-from .abcs import BadStatus, MissingBytes, OutFn, Transport
+from .abcs import BadStatusError, MissingBytesError, OutFn, Transport
 
 
 class Full(Transport):
@@ -37,17 +37,17 @@ class Full(Transport):
 
     def unpack(self, input: bytes | bytearray | memoryview, output: bytearray) -> int:
         if len(input) < 4:
-            raise MissingBytes(expected=4, got=len(input))
+            raise MissingBytesError(expected=4, got=len(input))
 
         length = struct.unpack_from(" 12, got: {length}")
 
         if len(input) < length:
-            raise MissingBytes(expected=length, got=len(input))
+            raise MissingBytesError(expected=length, got=len(input))
 
         seq = struct.unpack_from(" int:
         if len(input) < 4:
-            raise MissingBytes(expected=4, got=len(input))
+            raise MissingBytesError(expected=4, got=len(input))
 
         length = struct.unpack_from("= 4
                 and (status := struct.unpack(" 0, got: {length}")
 
diff --git a/client/src/telethon/_impl/mtsender/sender.py b/client/src/telethon/_impl/mtsender/sender.py
index 84533451..2cbb2ce8 100644
--- a/client/src/telethon/_impl/mtsender/sender.py
+++ b/client/src/telethon/_impl/mtsender/sender.py
@@ -10,9 +10,9 @@ from typing import Generic, Optional, Protocol, Self, Type, TypeVar
 
 from ..crypto import AuthKey
 from ..mtproto import (
-    BadMessage,
+    BadMessageError,
     Encrypted,
-    MissingBytes,
+    MissingBytesError,
     MsgId,
     Mtp,
     Plain,
@@ -133,7 +133,7 @@ class NotSerialized(RequestState):
 class Serialized(RequestState):
     __slots__ = ("msg_id", "container_msg_id")
 
-    def __init__(self, msg_id: MsgId):
+    def __init__(self, msg_id: MsgId) -> None:
         self.msg_id = msg_id
         self.container_msg_id = msg_id
 
@@ -141,7 +141,7 @@ class Serialized(RequestState):
 class Sent(RequestState):
     __slots__ = ("msg_id", "container_msg_id")
 
-    def __init__(self, msg_id: MsgId, container_msg_id: MsgId):
+    def __init__(self, msg_id: MsgId, container_msg_id: MsgId) -> None:
         self.msg_id = msg_id
         self.container_msg_id = container_msg_id
 
@@ -298,7 +298,7 @@ class Sender:
             self._mtp_buffer.clear()
             try:
                 n = self._transport.unpack(self._read_buffer, self._mtp_buffer)
-            except MissingBytes:
+            except MissingBytesError:
                 break
             else:
                 del self._read_buffer[:n]
@@ -403,7 +403,7 @@ class Sender:
                 result,
             )
 
-    def _process_bad_message(self, result: BadMessage) -> None:
+    def _process_bad_message(self, result: BadMessageError) -> None:
         for req in self._drain_requests(result.msg_id):
             if result.retryable:
                 self._logger.log(
diff --git a/client/src/telethon/_impl/session/__init__.py b/client/src/telethon/_impl/session/__init__.py
index 12613aad..7e9fcce9 100644
--- a/client/src/telethon/_impl/session/__init__.py
+++ b/client/src/telethon/_impl/session/__init__.py
@@ -11,7 +11,7 @@ from .message_box import (
     BOT_CHANNEL_DIFF_LIMIT,
     NO_UPDATES_TIMEOUT,
     USER_CHANNEL_DIFF_LIMIT,
-    Gap,
+    GapError,
     MessageBox,
     PossibleGap,
     PrematureEndReason,
@@ -32,7 +32,7 @@ __all__ = [
     "BOT_CHANNEL_DIFF_LIMIT",
     "NO_UPDATES_TIMEOUT",
     "USER_CHANNEL_DIFF_LIMIT",
-    "Gap",
+    "GapError",
     "MessageBox",
     "PossibleGap",
     "PrematureEndReason",
diff --git a/client/src/telethon/_impl/session/chat/hash_cache.py b/client/src/telethon/_impl/session/chat/hash_cache.py
index 60117029..36ab1da6 100644
--- a/client/src/telethon/_impl/session/chat/hash_cache.py
+++ b/client/src/telethon/_impl/session/chat/hash_cache.py
@@ -9,7 +9,7 @@ PeerRefType: TypeAlias = Type[UserRef] | Type[ChannelRef] | Type[GroupRef]
 class ChatHashCache:
     __slots__ = ("_hash_map", "_self_id", "_self_bot")
 
-    def __init__(self, self_user: Optional[tuple[int, bool]]):
+    def __init__(self, self_user: Optional[tuple[int, bool]]) -> None:
         self._hash_map: dict[int, tuple[PeerRefType, int]] = {}
         self._self_id = self_user[0] if self_user else None
         self._self_bot = self_user[1] if self_user else False
diff --git a/client/src/telethon/_impl/session/message_box/__init__.py b/client/src/telethon/_impl/session/message_box/__init__.py
index 2d075caf..ad6de917 100644
--- a/client/src/telethon/_impl/session/message_box/__init__.py
+++ b/client/src/telethon/_impl/session/message_box/__init__.py
@@ -2,7 +2,7 @@ from .defs import (
     BOT_CHANNEL_DIFF_LIMIT,
     NO_UPDATES_TIMEOUT,
     USER_CHANNEL_DIFF_LIMIT,
-    Gap,
+    GapError,
     PossibleGap,
     PrematureEndReason,
     PtsInfo,
@@ -14,7 +14,7 @@ __all__ = [
     "BOT_CHANNEL_DIFF_LIMIT",
     "NO_UPDATES_TIMEOUT",
     "USER_CHANNEL_DIFF_LIMIT",
-    "Gap",
+    "GapError",
     "PossibleGap",
     "PrematureEndReason",
     "PtsInfo",
diff --git a/client/src/telethon/_impl/session/message_box/adaptor.py b/client/src/telethon/_impl/session/message_box/adaptor.py
index 2eafb5bd..ca7b489e 100644
--- a/client/src/telethon/_impl/session/message_box/adaptor.py
+++ b/client/src/telethon/_impl/session/message_box/adaptor.py
@@ -2,7 +2,7 @@ from typing import Optional
 
 from ...tl import abcs, types
 from ..chat import ChatHashCache
-from .defs import ENTRY_ACCOUNT, ENTRY_SECRET, NO_SEQ, Gap, PtsInfo
+from .defs import ENTRY_ACCOUNT, ENTRY_SECRET, NO_SEQ, GapError, PtsInfo
 
 
 def updates_(updates: types.Updates) -> types.UpdatesCombined:
@@ -147,7 +147,7 @@ def update_short_sent_message(
 
 def adapt(updates: abcs.Updates, chat_hashes: ChatHashCache) -> types.UpdatesCombined:
     if isinstance(updates, types.UpdatesTooLong):
-        raise Gap
+        raise GapError
     elif isinstance(updates, types.UpdateShortMessage):
         return update_short_message(updates, chat_hashes.self_id)
     elif isinstance(updates, types.UpdateShortChatMessage):
diff --git a/client/src/telethon/_impl/session/message_box/defs.py b/client/src/telethon/_impl/session/message_box/defs.py
index 3033c921..07be30e4 100644
--- a/client/src/telethon/_impl/session/message_box/defs.py
+++ b/client/src/telethon/_impl/session/message_box/defs.py
@@ -80,6 +80,6 @@ class PrematureEndReason(Enum):
     BANNED = "ban"
 
 
-class Gap(ValueError):
+class GapError(ValueError):
     def __repr__(self) -> str:
         return "Gap()"
diff --git a/client/src/telethon/_impl/session/message_box/messagebox.py b/client/src/telethon/_impl/session/message_box/messagebox.py
index a93a01f9..54171c91 100644
--- a/client/src/telethon/_impl/session/message_box/messagebox.py
+++ b/client/src/telethon/_impl/session/message_box/messagebox.py
@@ -20,7 +20,7 @@ from .defs import (
     POSSIBLE_GAP_TIMEOUT,
     USER_CHANNEL_DIFF_LIMIT,
     Entry,
-    Gap,
+    GapError,
     PossibleGap,
     PrematureEndReason,
     State,
@@ -252,7 +252,7 @@ class MessageBox:
             )
             if can_recover:
                 self.try_begin_get_diff(ENTRY_ACCOUNT, "missing hash")
-                raise Gap
+                raise GapError
 
     # https://core.telegram.org/api/updates
     def process_updates(
@@ -281,7 +281,7 @@ class MessageBox:
                 return result, combined.users, combined.chats
             elif self.seq + 1 < combined.seq_start:
                 self.try_begin_get_diff(ENTRY_ACCOUNT, "detected gap")
-                raise Gap
+                raise GapError
 
         def update_sort_key(update: abcs.Update) -> int:
             pts = pts_info_from_update(update)
diff --git a/client/src/telethon/_impl/session/session.py b/client/src/telethon/_impl/session/session.py
index ccd46fc4..0fd5d291 100644
--- a/client/src/telethon/_impl/session/session.py
+++ b/client/src/telethon/_impl/session/session.py
@@ -168,7 +168,7 @@ class Session:
         dcs: Optional[list[DataCenter]] = None,
         user: Optional[User] = None,
         state: Optional[UpdateState] = None,
-    ):
+    ) -> None:
         self.dcs = dcs or []
         "List of known data-centers."
         self.user = user
diff --git a/client/src/telethon/_impl/session/storage/memory.py b/client/src/telethon/_impl/session/storage/memory.py
index eda1daaf..6ce16e0b 100644
--- a/client/src/telethon/_impl/session/storage/memory.py
+++ b/client/src/telethon/_impl/session/storage/memory.py
@@ -13,7 +13,7 @@ class MemorySession(Storage):
 
     __slots__ = ("session",)
 
-    def __init__(self, session: Optional[Session] = None):
+    def __init__(self, session: Optional[Session] = None) -> None:
         self.session = session
 
     async def load(self) -> Optional[Session]:
diff --git a/client/src/telethon/_impl/session/storage/sqlite.py b/client/src/telethon/_impl/session/storage/sqlite.py
index 2988e336..418a5cee 100644
--- a/client/src/telethon/_impl/session/storage/sqlite.py
+++ b/client/src/telethon/_impl/session/storage/sqlite.py
@@ -20,7 +20,7 @@ class SqliteSession(Storage):
     an VCS by accident (adding ``*.session`` to ``.gitignore`` will catch them).
     """
 
-    def __init__(self, file: str | Path):
+    def __init__(self, file: str | Path) -> None:
         path = Path(file)
         if not path.suffix:
             path = path.with_suffix(EXTENSION)
diff --git a/client/src/telethon/_impl/tl/core/reader.py b/client/src/telethon/_impl/tl/core/reader.py
index 3bb32a4c..c9103317 100644
--- a/client/src/telethon/_impl/tl/core/reader.py
+++ b/client/src/telethon/_impl/tl/core/reader.py
@@ -26,11 +26,11 @@ def _bootstrap_get_ty(constructor_id: int) -> Optional[Type["Serializable"]]:
             raise RuntimeError(
                 "generated api and mtproto schemas cannot have colliding constructor identifiers"
             )
-        ALL_TYPES = API_TYPES | MTPROTO_TYPES
+        all_types = API_TYPES | MTPROTO_TYPES
 
         # Signatures don't fully match, but this is a private method
         # and all previous uses are compatible with `dict.get`.
-        Reader._get_ty = ALL_TYPES.get  # type: ignore [assignment]
+        Reader._get_ty = all_types.get  # type: ignore [assignment]
 
     return Reader._get_ty(constructor_id)
 
diff --git a/client/src/telethon/_impl/tl/core/request.py b/client/src/telethon/_impl/tl/core/request.py
index b053bdd4..1234a2fe 100644
--- a/client/src/telethon/_impl/tl/core/request.py
+++ b/client/src/telethon/_impl/tl/core/request.py
@@ -17,9 +17,9 @@ def _bootstrap_get_deserializer(
             raise RuntimeError(
                 "generated api and mtproto schemas cannot have colliding constructor identifiers"
             )
-        ALL_DESER = API_DESER | MTPROTO_DESER
+        all_deser = API_DESER | MTPROTO_DESER
 
-        Request._get_deserializer = ALL_DESER.get  # type: ignore [assignment]
+        Request._get_deserializer = all_deser.get  # type: ignore [assignment]
 
     return Request._get_deserializer(constructor_id)
 
diff --git a/client/src/telethon/types/buttons.py b/client/src/telethon/types/buttons.py
index 3c857305..b67bb83f 100644
--- a/client/src/telethon/types/buttons.py
+++ b/client/src/telethon/types/buttons.py
@@ -19,6 +19,7 @@ and those you can define when using :meth:`telethon.Client.send_message`:
         buttons.Callback('Demo', b'data')
     ])
 """
+
 from .._impl.client.types.buttons import (
     Callback,
     RequestGeoLocation,
diff --git a/client/tests/mtproto_test.py b/client/tests/mtproto_test.py
index 6b184ca8..8ec99cd4 100644
--- a/client/tests/mtproto_test.py
+++ b/client/tests/mtproto_test.py
@@ -2,6 +2,7 @@ import struct
 from typing import Optional
 
 from pytest import raises
+
 from telethon._impl.crypto import AuthKey
 from telethon._impl.mtproto import Encrypted, Plain, RpcError
 from telethon._impl.mtproto.mtp.types import MsgId
diff --git a/client/tests/mtsender_test.py b/client/tests/mtsender_test.py
index 93ab7cee..0a9e2c59 100644
--- a/client/tests/mtsender_test.py
+++ b/client/tests/mtsender_test.py
@@ -2,6 +2,7 @@ import asyncio
 import logging
 
 from pytest import LogCaptureFixture, mark
+
 from telethon._impl.mtproto import Full
 from telethon._impl.mtsender import connect
 from telethon._impl.tl import LAYER, abcs, functions, types
diff --git a/client/tests/peer_ref_test.py b/client/tests/peer_ref_test.py
index 6a23246c..9c22bd7e 100644
--- a/client/tests/peer_ref_test.py
+++ b/client/tests/peer_ref_test.py
@@ -1,6 +1,7 @@
 import inspect
 
 from pytest import raises
+
 from telethon._impl.session import ChannelRef, GroupRef, PeerRef, UserRef
 
 USER = UserRef(12, 34)
diff --git a/client/tests/reader_test.py b/client/tests/reader_test.py
index 26037bfc..ca8ac16c 100644
--- a/client/tests/reader_test.py
+++ b/client/tests/reader_test.py
@@ -1,6 +1,7 @@
 import struct
 
 from pytest import mark
+
 from telethon._impl.tl.core import Reader, Serializable
 from telethon._impl.tl.mtproto.types import BadServerSalt
 from telethon._impl.tl.types import GeoPoint
diff --git a/client/tests/rsa_test.py b/client/tests/rsa_test.py
index 90986925..fe791fe9 100644
--- a/client/tests/rsa_test.py
+++ b/client/tests/rsa_test.py
@@ -1,4 +1,5 @@
 from rsa import PublicKey
+
 from telethon._impl.crypto.rsa import (
     PRODUCTION_RSA_KEY,
     TESTMODE_RSA_KEY,
diff --git a/client/tests/serializable_test.py b/client/tests/serializable_test.py
index f402186e..6ffbef41 100644
--- a/client/tests/serializable_test.py
+++ b/client/tests/serializable_test.py
@@ -1,4 +1,5 @@
 from pytest import mark
+
 from telethon._impl.tl.core import serialize_bytes_to
 
 
diff --git a/client/tests/transport/abridged_test.py b/client/tests/transport/abridged_test.py
index d3b425ab..0ef5ca60 100644
--- a/client/tests/transport/abridged_test.py
+++ b/client/tests/transport/abridged_test.py
@@ -1,4 +1,5 @@
 from pytest import raises
+
 from telethon._impl.mtproto import Abridged
 
 
diff --git a/client/tests/transport/full_test.py b/client/tests/transport/full_test.py
index 79441a86..c1e7f9bc 100644
--- a/client/tests/transport/full_test.py
+++ b/client/tests/transport/full_test.py
@@ -1,4 +1,5 @@
 from pytest import raises
+
 from telethon._impl.mtproto import Full
 
 
diff --git a/client/tests/transport/intermediate_test.py b/client/tests/transport/intermediate_test.py
index e9d55f39..52fe4761 100644
--- a/client/tests/transport/intermediate_test.py
+++ b/client/tests/transport/intermediate_test.py
@@ -1,4 +1,5 @@
 from pytest import raises
+
 from telethon._impl.mtproto import Intermediate
 
 
diff --git a/client/tests/two_factor_auth_test.py b/client/tests/two_factor_auth_test.py
index 40a60b82..32df3fba 100644
--- a/client/tests/two_factor_auth_test.py
+++ b/client/tests/two_factor_auth_test.py
@@ -1,4 +1,5 @@
 from pytest import mark, raises
+
 from telethon._impl.crypto.two_factor_auth import (
     calculate_2fa,
     check_p_prime_and_subgroup,
diff --git a/client/tests/types_test.py b/client/tests/types_test.py
index e19dc957..34bebe52 100644
--- a/client/tests/types_test.py
+++ b/client/tests/types_test.py
@@ -1,4 +1,5 @@
 from pytest import mark
+
 from telethon._impl.client.types import AdminRight
 from telethon._impl.tl import types
 
diff --git a/generator/pyproject.toml b/generator/pyproject.toml
index b0166ca2..84be3cbd 100644
--- a/generator/pyproject.toml
+++ b/generator/pyproject.toml
@@ -37,7 +37,11 @@ build-backend = "setuptools.build_meta"
 [tool.setuptools.dynamic]
 version = {attr = "telethon_generator.version.__version__"}
 
-[tool.ruff]
+[tool.ruff.lint]
+select = ["F", "E", "W", "I", "N", "ANN"]
 ignore = [
   "E501",  # formatter takes care of lines that are too long besides documentation
+  "ANN101",  # Missing type annotation for `self` in method
+  "ANN102",  # Missing type annotation for `cls` in classmethod
+  "ANN401",  # Dynamically typed expressions (typing.Any) are not type checked
 ]
diff --git a/generator/src/telethon_generator/_impl/tl_parser/__init__.py b/generator/src/telethon_generator/_impl/tl_parser/__init__.py
index 4a8d71e8..340ad473 100644
--- a/generator/src/telethon_generator/_impl/tl_parser/__init__.py
+++ b/generator/src/telethon_generator/_impl/tl_parser/__init__.py
@@ -7,7 +7,7 @@ from .tl import (
     NormalParameter,
     Parameter,
     Type,
-    TypeDefNotImplemented,
+    TypeDefNotImplementedError,
 )
 from .tl_iterator import FunctionDef, TypeDef
 from .tl_iterator import iterate as parse_tl_file
@@ -19,7 +19,7 @@ __all__ = [
     "Definition",
     "Flag",
     "Parameter",
-    "TypeDefNotImplemented",
+    "TypeDefNotImplementedError",
     "BaseParameter",
     "FlagsParameter",
     "NormalParameter",
diff --git a/generator/src/telethon_generator/_impl/tl_parser/tl/__init__.py b/generator/src/telethon_generator/_impl/tl_parser/tl/__init__.py
index 0352a18f..e29213bd 100644
--- a/generator/src/telethon_generator/_impl/tl_parser/tl/__init__.py
+++ b/generator/src/telethon_generator/_impl/tl_parser/tl/__init__.py
@@ -1,6 +1,6 @@
 from .definition import Definition
 from .flag import Flag
-from .parameter import Parameter, TypeDefNotImplemented
+from .parameter import Parameter, TypeDefNotImplementedError
 from .parameter_type import BaseParameter, FlagsParameter, NormalParameter
 from .ty import Type
 
@@ -8,7 +8,7 @@ __all__ = [
     "Definition",
     "Flag",
     "Parameter",
-    "TypeDefNotImplemented",
+    "TypeDefNotImplementedError",
     "BaseParameter",
     "FlagsParameter",
     "NormalParameter",
diff --git a/generator/src/telethon_generator/_impl/tl_parser/tl/definition.py b/generator/src/telethon_generator/_impl/tl_parser/tl/definition.py
index 70adf636..cb234740 100644
--- a/generator/src/telethon_generator/_impl/tl_parser/tl/definition.py
+++ b/generator/src/telethon_generator/_impl/tl_parser/tl/definition.py
@@ -2,7 +2,7 @@ from dataclasses import dataclass
 from typing import Self
 
 from ..utils import infer_id
-from .parameter import Parameter, TypeDefNotImplemented
+from .parameter import Parameter, TypeDefNotImplementedError
 from .parameter_type import FlagsParameter, NormalParameter
 from .ty import Type
 
@@ -65,7 +65,7 @@ class Definition:
         for param_str in middle.split():
             try:
                 param = Parameter.from_str(param_str)
-            except TypeDefNotImplemented as e:
+            except TypeDefNotImplementedError as e:
                 type_defs.append(e.name)
                 continue
 
diff --git a/generator/src/telethon_generator/_impl/tl_parser/tl/parameter.py b/generator/src/telethon_generator/_impl/tl_parser/tl/parameter.py
index c32e93df..7c204623 100644
--- a/generator/src/telethon_generator/_impl/tl_parser/tl/parameter.py
+++ b/generator/src/telethon_generator/_impl/tl_parser/tl/parameter.py
@@ -4,8 +4,8 @@ from typing import Self
 from .parameter_type import BaseParameter
 
 
-class TypeDefNotImplemented(NotImplementedError):
-    def __init__(self, name: str):
+class TypeDefNotImplementedError(NotImplementedError):
+    def __init__(self, name: str) -> None:
         super().__init__(f"typedef not implemented: {name}")
         self.name = name
 
@@ -19,7 +19,7 @@ class Parameter:
     def from_str(cls, param: str) -> Self:
         if param.startswith("{"):
             if param.endswith(":Type}"):
-                raise TypeDefNotImplemented(param[1 : param.index(":")])
+                raise TypeDefNotImplementedError(param[1 : param.index(":")])
             else:
                 raise ValueError("missing def")
 
diff --git a/generator/src/telethon_generator/tl_parser/__init__.py b/generator/src/telethon_generator/tl_parser/__init__.py
index 3816164c..4d180f51 100644
--- a/generator/src/telethon_generator/tl_parser/__init__.py
+++ b/generator/src/telethon_generator/tl_parser/__init__.py
@@ -9,7 +9,7 @@ from .._impl.tl_parser import (
     ParsedTl,
     Type,
     TypeDef,
-    TypeDefNotImplemented,
+    TypeDefNotImplementedError,
     load_tl_file,
     parse_tl_file,
 )
@@ -19,7 +19,7 @@ __all__ = [
     "Flag",
     "Parameter",
     "ParsedTl",
-    "TypeDefNotImplemented",
+    "TypeDefNotImplementedError",
     "BaseParameter",
     "FlagsParameter",
     "NormalParameter",
diff --git a/generator/tests/common_test.py b/generator/tests/common_test.py
index f94be28d..616bf073 100644
--- a/generator/tests/common_test.py
+++ b/generator/tests/common_test.py
@@ -1,4 +1,5 @@
 from pytest import mark
+
 from telethon_generator._impl.codegen.serde.common import (
     split_words,
     to_class_name,
diff --git a/generator/tests/definition_test.py b/generator/tests/definition_test.py
index e395d77e..1f3d3909 100644
--- a/generator/tests/definition_test.py
+++ b/generator/tests/definition_test.py
@@ -1,4 +1,5 @@
 from pytest import mark, raises
+
 from telethon_generator.tl_parser import (
     Definition,
     Flag,
diff --git a/generator/tests/parameter_test.py b/generator/tests/parameter_test.py
index 6daf7bbd..6aeacae2 100644
--- a/generator/tests/parameter_test.py
+++ b/generator/tests/parameter_test.py
@@ -1,4 +1,5 @@
 from pytest import mark, raises
+
 from telethon_generator.tl_parser import (
     Flag,
     FlagsParameter,
diff --git a/generator/tests/tl_iterator_test.py b/generator/tests/tl_iterator_test.py
index 2e2bb6e6..b4d41bc4 100644
--- a/generator/tests/tl_iterator_test.py
+++ b/generator/tests/tl_iterator_test.py
@@ -1,4 +1,5 @@
 from pytest import raises
+
 from telethon_generator.tl_parser import FunctionDef, TypeDef, parse_tl_file
 
 
diff --git a/generator/tests/ty_test.py b/generator/tests/ty_test.py
index 3effb0bf..8a1f4443 100644
--- a/generator/tests/ty_test.py
+++ b/generator/tests/ty_test.py
@@ -1,6 +1,7 @@
 from typing import Optional
 
 from pytest import mark, raises
+
 from telethon_generator.tl_parser import Type
 
 
diff --git a/tools/check.py b/tools/check.py
index 3fdf3174..c587d974 100644
--- a/tools/check.py
+++ b/tools/check.py
@@ -1,6 +1,7 @@
 """
 Check formatting, type-check and run offline tests.
 """
+
 import subprocess
 import sys
 import tempfile
@@ -15,9 +16,7 @@ def run(*args: str) -> int:
 def main() -> None:
     with tempfile.TemporaryDirectory() as tmp_dir:
         exit(
-            run("isort", ".", "-c", "--profile", "black", "--gitignore")
-            or run("black", ".", "--check", "--extend-exclude", BLACK_IGNORE)
-            or run("mypy", "--strict", ".")
+            run("mypy", "--strict", ".")
             or run("ruff", "check", ".")
             or run("sphinx", "-M", "dummy", "client/doc", tmp_dir, "-n", "-W")
             or run("pytest", ".", "-m", "not net")
diff --git a/tools/codegen.py b/tools/codegen.py
index 64a4dc16..316d195c 100644
--- a/tools/codegen.py
+++ b/tools/codegen.py
@@ -2,6 +2,7 @@
 Run `telethon_generator.codegen` on both `api.tl` and `mtproto.tl` to output
 corresponding Python code in the default directories under the `client/`.
 """
+
 import subprocess
 import sys
 
diff --git a/tools/copy_client_signatures.py b/tools/copy_client_signatures.py
index d3e48520..219de610 100644
--- a/tools/copy_client_signatures.py
+++ b/tools/copy_client_signatures.py
@@ -110,13 +110,13 @@ def main() -> None:
             function.args.args[0].annotation = None
 
         if isinstance(function, ast.AsyncFunctionDef):
-            call = ast.Await(value=call)
+            call = ast.Await(value=call)  # type: ignore [arg-type]
 
         match function.returns:
             case ast.Constant(value=None):
-                call = ast.Expr(value=call)
+                call = ast.Expr(value=call)  # type: ignore [arg-type]
             case _:
-                call = ast.Return(value=call)
+                call = ast.Return(value=call)  # type: ignore [arg-type]
 
         function.body.append(call)
         class_body.append(function)
diff --git a/tools/docgen.py b/tools/docgen.py
index 29ed054f..916a3895 100644
--- a/tools/docgen.py
+++ b/tools/docgen.py
@@ -1,6 +1,7 @@
 """
 Run `sphinx-build` to create HTML documentation and detect errors.
 """
+
 import subprocess
 import sys
 
diff --git a/tools/fmt.py b/tools/fmt.py
index fde86123..08cbb06e 100644
--- a/tools/fmt.py
+++ b/tools/fmt.py
@@ -1,6 +1,7 @@
 """
 Sort imports and format code.
 """
+
 import subprocess
 import sys