From 84f966782685d6aa008498fba028f47cca9fea75 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Fri, 4 Aug 2023 00:10:57 +0300 Subject: [PATCH] Fixed mypy errors --- .butcher/types/Message/aliases.yml | 49 +++++- aiogram/types/error_event.py | 4 +- aiogram/types/message.py | 236 ++++++++++++++++++++++++++--- aiogram/utils/formatting.py | 1 + aiogram/utils/keyboard.py | 10 +- 5 files changed, 271 insertions(+), 29 deletions(-) diff --git a/.butcher/types/Message/aliases.yml b/.butcher/types/Message/aliases.yml index 290f9fa1..341919cc 100644 --- a/.butcher/types/Message/aliases.yml +++ b/.butcher/types/Message/aliases.yml @@ -1,195 +1,242 @@ answer: method: sendMessage + code: &assert-chat | + assert self.chat is not None, "This method can be used only if chat is present in the message." fill: &fill-answer chat_id: self.chat.id message_thread_id: self.message_thread_id if self.is_topic_message else None reply: method: sendMessage + code: *assert-chat fill: &fill-reply <<: *fill-answer reply_to_message_id: self.message_id answer_animation: method: sendAnimation + code: *assert-chat fill: *fill-answer reply_animation: method: sendAnimation + code: *assert-chat fill: *fill-reply answer_audio: method: sendAudio + code: *assert-chat fill: *fill-answer reply_audio: method: sendAudio + code: *assert-chat fill: *fill-reply answer_contact: method: sendContact + code: *assert-chat fill: *fill-answer reply_contact: method: sendContact + code: *assert-chat fill: *fill-reply answer_document: method: sendDocument + code: *assert-chat fill: *fill-answer reply_document: method: sendDocument + code: *assert-chat fill: *fill-reply answer_game: method: sendGame + code: *assert-chat fill: *fill-answer reply_game: method: sendGame + code: *assert-chat fill: *fill-reply answer_invoice: method: sendInvoice + code: *assert-chat fill: *fill-answer reply_invoice: method: sendInvoice + code: *assert-chat fill: *fill-reply answer_location: method: sendLocation + code: *assert-chat fill: *fill-answer reply_location: method: sendLocation + code: *assert-chat fill: *fill-reply answer_media_group: method: sendMediaGroup + code: *assert-chat fill: *fill-answer reply_media_group: method: sendMediaGroup + code: *assert-chat fill: *fill-reply answer_photo: method: sendPhoto + code: *assert-chat fill: *fill-answer reply_photo: method: sendPhoto + code: *assert-chat fill: *fill-reply answer_poll: method: sendPoll + code: *assert-chat fill: *fill-answer reply_poll: method: sendPoll + code: *assert-chat fill: *fill-reply answer_dice: method: sendDice + code: *assert-chat fill: *fill-answer reply_dice: method: sendDice + code: *assert-chat fill: *fill-reply answer_sticker: method: sendSticker + code: *assert-chat fill: *fill-answer reply_sticker: method: sendSticker + code: *assert-chat fill: *fill-reply answer_venue: method: sendVenue + code: *assert-chat fill: *fill-answer reply_venue: method: sendVenue + code: *assert-chat fill: *fill-reply answer_video: method: sendVideo + code: *assert-chat fill: *fill-answer reply_video: method: sendVideo + code: *assert-chat fill: *fill-reply answer_video_note: method: sendVideoNote + code: *assert-chat fill: *fill-answer reply_video_note: method: sendVideoNote + code: *assert-chat fill: *fill-reply answer_voice: method: sendVoice + code: *assert-chat fill: *fill-answer reply_voice: method: sendVoice + code: *assert-chat fill: *fill-reply copy_to: method: copyMessage + code: *assert-chat fill: from_chat_id: self.chat.id message_id: self.message_id forward: method: forwardMessage + code: *assert-chat fill: from_chat_id: self.chat.id message_id: self.message_id edit_text: method: editMessageText + code: *assert-chat fill: &message-target - chat_id: self.chat.id if self.chat else None + chat_id: self.chat.id message_id: self.message_id edit_media: method: editMessageMedia fill: *message-target + code: *assert-chat edit_reply_markup: method: editMessageReplyMarkup + code: *assert-chat fill: *message-target delete_reply_markup: method: editMessageReplyMarkup + code: *assert-chat fill: <<: *message-target reply_markup: None edit_live_location: method: editMessageLiveLocation + code: *assert-chat fill: *message-target stop_live_location: method: stopMessageLiveLocation + code: *assert-chat fill: *message-target edit_caption: method: editMessageCaption + code: *assert-chat fill: *message-target delete: method: deleteMessage + code: *assert-chat fill: *message-target pin: method: pinChatMessage + code: *assert-chat fill: *message-target unpin: method: unpinChatMessage + code: *assert-chat fill: *message-target diff --git a/aiogram/types/error_event.py b/aiogram/types/error_event.py index 929e5dce..e5eafc9c 100644 --- a/aiogram/types/error_event.py +++ b/aiogram/types/error_event.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any from aiogram.types.base import TelegramObject @@ -23,6 +23,6 @@ class ErrorEvent(TelegramObject): if TYPE_CHECKING: def __init__( - __pydantic_self__, *, update: Update, exception: Exception, **__pydantic_kwargs + __pydantic_self__, *, update: Update, exception: Exception, **__pydantic_kwargs: Any ) -> None: super().__init__(update=update, exception=exception, **__pydantic_kwargs) diff --git a/aiogram/types/message.py b/aiogram/types/message.py index 96e751b8..58a491b8 100644 --- a/aiogram/types/message.py +++ b/aiogram/types/message.py @@ -1,7 +1,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, Any, List, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union from pydantic import Field @@ -559,6 +559,10 @@ class Message(TelegramObject): from aiogram.methods import SendAnimation + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendAnimation( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -631,6 +635,10 @@ class Message(TelegramObject): from aiogram.methods import SendAnimation + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendAnimation( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -701,6 +709,10 @@ class Message(TelegramObject): from aiogram.methods import SendAudio + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendAudio( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -771,6 +783,10 @@ class Message(TelegramObject): from aiogram.methods import SendAudio + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendAudio( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -831,6 +847,10 @@ class Message(TelegramObject): from aiogram.methods import SendContact + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendContact( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -888,6 +908,10 @@ class Message(TelegramObject): from aiogram.methods import SendContact + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendContact( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -948,6 +972,10 @@ class Message(TelegramObject): from aiogram.methods import SendDocument + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendDocument( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1011,6 +1039,10 @@ class Message(TelegramObject): from aiogram.methods import SendDocument + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendDocument( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1061,6 +1093,10 @@ class Message(TelegramObject): from aiogram.methods import SendGame + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendGame( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1107,6 +1143,10 @@ class Message(TelegramObject): from aiogram.methods import SendGame + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendGame( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1192,6 +1232,10 @@ class Message(TelegramObject): from aiogram.methods import SendInvoice + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendInvoice( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1298,6 +1342,10 @@ class Message(TelegramObject): from aiogram.methods import SendInvoice + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendInvoice( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1375,6 +1423,10 @@ class Message(TelegramObject): from aiogram.methods import SendLocation + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendLocation( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1438,6 +1490,10 @@ class Message(TelegramObject): from aiogram.methods import SendLocation + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendLocation( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1486,6 +1542,10 @@ class Message(TelegramObject): from aiogram.methods import SendMediaGroup + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendMediaGroup( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1529,6 +1589,10 @@ class Message(TelegramObject): from aiogram.methods import SendMediaGroup + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendMediaGroup( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1581,6 +1645,10 @@ class Message(TelegramObject): from aiogram.methods import SendMessage + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendMessage( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1638,6 +1706,10 @@ class Message(TelegramObject): from aiogram.methods import SendMessage + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendMessage( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1696,6 +1768,10 @@ class Message(TelegramObject): from aiogram.methods import SendPhoto + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendPhoto( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1756,6 +1832,10 @@ class Message(TelegramObject): from aiogram.methods import SendPhoto + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendPhoto( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1829,6 +1909,10 @@ class Message(TelegramObject): from aiogram.methods import SendPoll + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendPoll( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1910,6 +1994,10 @@ class Message(TelegramObject): from aiogram.methods import SendPoll + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendPoll( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -1968,6 +2056,10 @@ class Message(TelegramObject): from aiogram.methods import SendDice + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendDice( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2016,6 +2108,10 @@ class Message(TelegramObject): from aiogram.methods import SendDice + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendDice( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2065,6 +2161,10 @@ class Message(TelegramObject): from aiogram.methods import SendSticker + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendSticker( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2116,6 +2216,10 @@ class Message(TelegramObject): from aiogram.methods import SendSticker + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendSticker( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2178,6 +2282,10 @@ class Message(TelegramObject): from aiogram.methods import SendVenue + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendVenue( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2247,6 +2355,10 @@ class Message(TelegramObject): from aiogram.methods import SendVenue + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendVenue( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2319,6 +2431,10 @@ class Message(TelegramObject): from aiogram.methods import SendVideo + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendVideo( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2394,6 +2510,10 @@ class Message(TelegramObject): from aiogram.methods import SendVideo + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendVideo( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2456,6 +2576,10 @@ class Message(TelegramObject): from aiogram.methods import SendVideoNote + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendVideoNote( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2513,6 +2637,10 @@ class Message(TelegramObject): from aiogram.methods import SendVideoNote + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendVideoNote( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2571,6 +2699,10 @@ class Message(TelegramObject): from aiogram.methods import SendVoice + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendVoice( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2631,6 +2763,10 @@ class Message(TelegramObject): from aiogram.methods import SendVoice + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return SendVoice( chat_id=self.chat.id, message_thread_id=self.message_thread_id if self.is_topic_message else None, @@ -2672,14 +2808,14 @@ class Message(TelegramObject): SendVoice, ]: """ - Send copy of message. + Send copy of a message. Is similar to :meth:`aiogram.client.bot.Bot.copy_message` but returning the sent message instead of :class:`aiogram.types.message_id.MessageId` .. note:: - This method don't use the API method named `copyMessage` and + This method doesn't use the API method named `copyMessage` and historically implemented before the similar method is added to API :param chat_id: @@ -2707,7 +2843,7 @@ class Message(TelegramObject): SendVoice, ) - kwargs = { + kwargs: Dict[str, Any] = { "chat_id": chat_id, "reply_markup": reply_markup or self.reply_markup, "disable_notification": disable_notification, @@ -2715,38 +2851,48 @@ class Message(TelegramObject): "message_thread_id": message_thread_id, "allow_sending_without_reply": allow_sending_without_reply, } - text = self.text or self.caption - entities = self.entities or self.caption_entities if self.text: - return SendMessage(text=text, entities=entities, **kwargs).as_(self._bot) + return SendMessage(text=self.text, entities=self.entities, **kwargs).as_(self._bot) if self.audio: return SendAudio( audio=self.audio.file_id, - caption=text, + caption=self.caption, title=self.audio.title, performer=self.audio.performer, duration=self.audio.duration, - caption_entities=entities, + caption_entities=self.caption_entities, **kwargs, ).as_(self._bot) if self.animation: return SendAnimation( - animation=self.animation.file_id, caption=text, caption_entities=entities, **kwargs + animation=self.animation.file_id, + caption=self.caption, + caption_entities=self.caption_entities, + **kwargs, ).as_(self._bot) if self.document: return SendDocument( - document=self.document.file_id, caption=text, caption_entities=entities, **kwargs + document=self.document.file_id, + caption=self.caption, + caption_entities=self.caption_entities, + **kwargs, ).as_(self._bot) if self.photo: return SendPhoto( - photo=self.photo[-1].file_id, caption=text, caption_entities=entities, **kwargs + photo=self.photo[-1].file_id, + caption=self.caption, + caption_entities=self.caption_entities, + **kwargs, ).as_(self._bot) if self.sticker: return SendSticker(sticker=self.sticker.file_id, **kwargs) if self.video: return SendVideo( - video=self.video.file_id, caption=text, caption_entities=entities, **kwargs + video=self.video.file_id, + caption=self.caption, + caption_entities=self.caption_entities, + **kwargs, ).as_(self._bot) if self.video_note: return SendVideoNote(video_note=self.video_note.file_id, **kwargs).as_(self._bot) @@ -2829,6 +2975,10 @@ class Message(TelegramObject): from aiogram.methods import CopyMessage + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return CopyMessage( from_chat_id=self.chat.id, message_id=self.message_id, @@ -2879,8 +3029,12 @@ class Message(TelegramObject): from aiogram.methods import EditMessageText + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return EditMessageText( - chat_id=self.chat.id if self.chat else None, + chat_id=self.chat.id, message_id=self.message_id, text=text, inline_message_id=inline_message_id, @@ -2965,8 +3119,12 @@ class Message(TelegramObject): from aiogram.methods import EditMessageMedia + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return EditMessageMedia( - chat_id=self.chat.id if self.chat else None, + chat_id=self.chat.id, message_id=self.message_id, media=media, inline_message_id=inline_message_id, @@ -3000,8 +3158,12 @@ class Message(TelegramObject): from aiogram.methods import EditMessageReplyMarkup + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return EditMessageReplyMarkup( - chat_id=self.chat.id if self.chat else None, + chat_id=self.chat.id, message_id=self.message_id, inline_message_id=inline_message_id, reply_markup=reply_markup, @@ -3033,8 +3195,12 @@ class Message(TelegramObject): from aiogram.methods import EditMessageReplyMarkup + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return EditMessageReplyMarkup( - chat_id=self.chat.id if self.chat else None, + chat_id=self.chat.id, message_id=self.message_id, reply_markup=None, inline_message_id=inline_message_id, @@ -3077,8 +3243,12 @@ class Message(TelegramObject): from aiogram.methods import EditMessageLiveLocation + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return EditMessageLiveLocation( - chat_id=self.chat.id if self.chat else None, + chat_id=self.chat.id, message_id=self.message_id, latitude=latitude, longitude=longitude, @@ -3116,8 +3286,12 @@ class Message(TelegramObject): from aiogram.methods import StopMessageLiveLocation + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return StopMessageLiveLocation( - chat_id=self.chat.id if self.chat else None, + chat_id=self.chat.id, message_id=self.message_id, inline_message_id=inline_message_id, reply_markup=reply_markup, @@ -3156,8 +3330,12 @@ class Message(TelegramObject): from aiogram.methods import EditMessageCaption + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return EditMessageCaption( - chat_id=self.chat.id if self.chat else None, + chat_id=self.chat.id, message_id=self.message_id, inline_message_id=inline_message_id, caption=caption, @@ -3207,8 +3385,12 @@ class Message(TelegramObject): from aiogram.methods import DeleteMessage + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return DeleteMessage( - chat_id=self.chat.id if self.chat else None, + chat_id=self.chat.id, message_id=self.message_id, **kwargs, ).as_(self._bot) @@ -3237,8 +3419,12 @@ class Message(TelegramObject): from aiogram.methods import PinChatMessage + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return PinChatMessage( - chat_id=self.chat.id if self.chat else None, + chat_id=self.chat.id, message_id=self.message_id, disable_notification=disable_notification, **kwargs, @@ -3266,8 +3452,12 @@ class Message(TelegramObject): from aiogram.methods import UnpinChatMessage + assert ( + self.chat is not None + ), "This method can be used only if chat is present in the message." + return UnpinChatMessage( - chat_id=self.chat.id if self.chat else None, + chat_id=self.chat.id, message_id=self.message_id, **kwargs, ).as_(self._bot) diff --git a/aiogram/utils/formatting.py b/aiogram/utils/formatting.py index da00f423..2379418a 100644 --- a/aiogram/utils/formatting.py +++ b/aiogram/utils/formatting.py @@ -98,6 +98,7 @@ class Text(Iterable[NodeType]): return text, entities def _render_entity(self, *, offset: int, length: int) -> MessageEntity: + assert self.type is not None, "Node without type can't be rendered as entity" return MessageEntity(type=self.type, offset=offset, length=length, **self._params) def as_kwargs( diff --git a/aiogram/utils/keyboard.py b/aiogram/utils/keyboard.py index 84258e6d..d276bcbe 100644 --- a/aiogram/utils/keyboard.py +++ b/aiogram/utils/keyboard.py @@ -1,5 +1,6 @@ from __future__ import annotations +from abc import ABC from copy import deepcopy from itertools import chain from itertools import cycle as repeat_all @@ -14,6 +15,7 @@ from typing import ( Type, TypeVar, Union, + cast, no_type_check, ) @@ -35,7 +37,7 @@ MIN_WIDTH = 1 MAX_BUTTONS = 100 -class KeyboardBuilder(Generic[ButtonType]): +class KeyboardBuilder(Generic[ButtonType], ABC): """ Generic keyboard builder that helps to adjust your markup with defined shape of lines. @@ -243,8 +245,10 @@ class KeyboardBuilder(Generic[ButtonType]): def as_markup(self, **kwargs: Any) -> Union[InlineKeyboardMarkup, ReplyKeyboardMarkup]: if self._button_type is KeyboardButton: - return ReplyKeyboardMarkup(keyboard=self.export(), **kwargs) - return InlineKeyboardMarkup(inline_keyboard=self.export()) + keyboard = cast(List[List[KeyboardButton]], self.export()) # type: ignore + return ReplyKeyboardMarkup(keyboard=keyboard, **kwargs) + inline_keyboard = cast(List[List[InlineKeyboardButton]], self.export()) # type: ignore + return InlineKeyboardMarkup(inline_keyboard=inline_keyboard) def repeat_last(items: Iterable[T]) -> Generator[T, None, None]: