From 023245c76b0d49468ffd0affbcae0424f7a4aa90 Mon Sep 17 00:00:00 2001 From: Dima Boger Date: Sun, 12 Apr 2020 17:16:35 +0300 Subject: [PATCH 01/11] :sparkles: Add sentinel value for parse_mode which can be None itself Resolves #302. We decided to use sentinel pattern (https://python-patterns.guide/python/sentinel-object/) as a solution, but got a few problems with plain `object()`, so instead we use unittest.mock.sentinel and we hope it won't cause side effects. Most of work done via tg-codegen (https://github.com/aiogram/tg-codegen/pull/1), so it's good to review only implementation of sentinel, processing sentinel in `prepare_parse_mode`, changes in base method model and little test fixes. --- aiogram/api/client/bot.py | 19 +++++---- aiogram/api/methods/base.py | 42 ++++++++++++++----- aiogram/api/methods/edit_message_caption.py | 4 +- aiogram/api/methods/edit_message_text.py | 4 +- aiogram/api/methods/send_animation.py | 3 +- aiogram/api/methods/send_audio.py | 3 +- aiogram/api/methods/send_document.py | 3 +- aiogram/api/methods/send_message.py | 3 +- aiogram/api/methods/send_photo.py | 3 +- aiogram/api/methods/send_video.py | 3 +- aiogram/api/methods/send_voice.py | 3 +- aiogram/api/types/__init__.py | 3 +- aiogram/api/types/base.py | 6 +++ .../api/types/inline_query_result_audio.py | 3 +- .../types/inline_query_result_cached_audio.py | 3 +- .../inline_query_result_cached_document.py | 3 +- .../types/inline_query_result_cached_gif.py | 3 +- .../inline_query_result_cached_mpeg4_gif.py | 3 +- .../types/inline_query_result_cached_photo.py | 3 +- .../types/inline_query_result_cached_video.py | 3 +- .../types/inline_query_result_cached_voice.py | 3 +- .../api/types/inline_query_result_document.py | 3 +- aiogram/api/types/inline_query_result_gif.py | 3 +- .../types/inline_query_result_mpeg4_gif.py | 3 +- .../api/types/inline_query_result_photo.py | 3 +- .../api/types/inline_query_result_video.py | 3 +- .../api/types/inline_query_result_voice.py | 3 +- aiogram/api/types/input_media_animation.py | 3 +- aiogram/api/types/input_media_audio.py | 3 +- aiogram/api/types/input_media_document.py | 3 +- aiogram/api/types/input_media_photo.py | 3 +- aiogram/api/types/input_media_video.py | 3 +- .../api/types/input_text_message_content.py | 3 +- tests/test_api/test_methods/test_base.py | 2 +- 34 files changed, 108 insertions(+), 53 deletions(-) diff --git a/aiogram/api/client/bot.py b/aiogram/api/client/bot.py index 27293d83..56cedcf8 100644 --- a/aiogram/api/client/bot.py +++ b/aiogram/api/client/bot.py @@ -82,6 +82,7 @@ from ..methods import ( UploadStickerFile, ) from ..types import ( + UNSET, BotCommand, Chat, ChatMember, @@ -339,7 +340,7 @@ class Bot(ContextInstanceMixin["Bot"]): self, chat_id: Union[int, str], text: str, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_web_page_preview: Optional[bool] = None, disable_notification: Optional[bool] = None, reply_to_message_id: Optional[int] = None, @@ -411,7 +412,7 @@ class Bot(ContextInstanceMixin["Bot"]): chat_id: Union[int, str], photo: Union[InputFile, str], caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_notification: Optional[bool] = None, reply_to_message_id: Optional[int] = None, reply_markup: Optional[ @@ -457,7 +458,7 @@ class Bot(ContextInstanceMixin["Bot"]): chat_id: Union[int, str], audio: Union[InputFile, str], caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, duration: Optional[int] = None, performer: Optional[str] = None, title: Optional[str] = None, @@ -525,7 +526,7 @@ class Bot(ContextInstanceMixin["Bot"]): document: Union[InputFile, str], thumb: Optional[Union[InputFile, str]] = None, caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_notification: Optional[bool] = None, reply_to_message_id: Optional[int] = None, reply_markup: Optional[ @@ -585,7 +586,7 @@ class Bot(ContextInstanceMixin["Bot"]): height: Optional[int] = None, thumb: Optional[Union[InputFile, str]] = None, caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, supports_streaming: Optional[bool] = None, disable_notification: Optional[bool] = None, reply_to_message_id: Optional[int] = None, @@ -654,7 +655,7 @@ class Bot(ContextInstanceMixin["Bot"]): height: Optional[int] = None, thumb: Optional[Union[InputFile, str]] = None, caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_notification: Optional[bool] = None, reply_to_message_id: Optional[int] = None, reply_markup: Optional[ @@ -716,7 +717,7 @@ class Bot(ContextInstanceMixin["Bot"]): chat_id: Union[int, str], voice: Union[InputFile, str], caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, duration: Optional[int] = None, disable_notification: Optional[bool] = None, reply_to_message_id: Optional[int] = None, @@ -1696,7 +1697,7 @@ class Bot(ContextInstanceMixin["Bot"]): chat_id: Optional[Union[int, str]] = None, message_id: Optional[int] = None, inline_message_id: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_web_page_preview: Optional[bool] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, ) -> Union[Message, bool]: @@ -1738,7 +1739,7 @@ class Bot(ContextInstanceMixin["Bot"]): message_id: Optional[int] = None, inline_message_id: Optional[str] = None, caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, reply_markup: Optional[InlineKeyboardMarkup] = None, ) -> Union[Message, bool]: """ diff --git a/aiogram/api/methods/base.py b/aiogram/api/methods/base.py index 72eafa05..35d5abe1 100644 --- a/aiogram/api/methods/base.py +++ b/aiogram/api/methods/base.py @@ -4,10 +4,10 @@ import abc import secrets from typing import TYPE_CHECKING, Any, Dict, Generator, Generic, Optional, TypeVar, Union -from pydantic import BaseConfig, BaseModel, Extra +from pydantic import BaseConfig, BaseModel, Extra, root_validator from pydantic.generics import GenericModel -from ..types import InputFile, ResponseParameters +from ..types import UNSET, InputFile, ResponseParameters if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot @@ -46,6 +46,20 @@ class TelegramMethod(abc.ABC, BaseModel, Generic[T]): arbitrary_types_allowed = True orm_mode = True + @root_validator(pre=True) + def remove_unset(cls, values: Dict[str, Any]) -> Dict[str, Any]: + """ + Remove UNSET from `parse_mode` before fields validation. + + We use UNSET as a sentinel value for `parse_mode` and replace it to real value later. + It isn't a problem when it's just default value for a model field, but UNSET might be passing to + a model initialization from `Bot.method_name`, so we must take care of it and + remove it before fields validation. + """ + if "parse_mode" in values and values["parse_mode"] is UNSET: + values.pop("parse_mode") + return values + @property @abc.abstractmethod def __returning__(self) -> type: # pragma: no cover @@ -106,18 +120,24 @@ def prepare_media_file(data: Dict[str, Any], files: Dict[str, InputFile]) -> Non def prepare_parse_mode(root: Any) -> None: + """ + Find and set parse_mode with highest priority. + + Developer can manually set parse_mode for each message (or message-like) object, + but if parse_mode was unset we should use value from Bot object. + + We can't use None for "unset state", because None itself is the parse_mode option. + """ if isinstance(root, list): for item in root: prepare_parse_mode(item) return - if root.get("parse_mode"): - return + if root.get("parse_mode", UNSET) is UNSET: + from ..client.bot import Bot - from ..client.bot import Bot - - bot = Bot.get_current(no_error=True) - if bot and bot.parse_mode: - root["parse_mode"] = bot.parse_mode - return - return + bot = Bot.get_current(no_error=True) + if bot and bot.parse_mode: + root["parse_mode"] = bot.parse_mode + else: + root["parse_mode"] = None diff --git a/aiogram/api/methods/edit_message_caption.py b/aiogram/api/methods/edit_message_caption.py index 75b5cc69..ebbe9c7b 100644 --- a/aiogram/api/methods/edit_message_caption.py +++ b/aiogram/api/methods/edit_message_caption.py @@ -1,6 +1,6 @@ from typing import Any, Dict, Optional, Union -from ..types import InlineKeyboardMarkup, Message +from ..types import UNSET, InlineKeyboardMarkup, Message from .base import Request, TelegramMethod, prepare_parse_mode @@ -23,7 +23,7 @@ class EditMessageCaption(TelegramMethod[Union[Message, bool]]): """Required if chat_id and message_id are not specified. Identifier of the inline message""" caption: Optional[str] = None """New caption of the message, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/methods/edit_message_text.py b/aiogram/api/methods/edit_message_text.py index 5c3c4c4c..20098fdc 100644 --- a/aiogram/api/methods/edit_message_text.py +++ b/aiogram/api/methods/edit_message_text.py @@ -1,6 +1,6 @@ from typing import Any, Dict, Optional, Union -from ..types import InlineKeyboardMarkup, Message +from ..types import UNSET, InlineKeyboardMarkup, Message from .base import Request, TelegramMethod @@ -23,7 +23,7 @@ class EditMessageText(TelegramMethod[Union[Message, bool]]): """Required if inline_message_id is not specified. Identifier of the message to edit""" inline_message_id: Optional[str] = None """Required if chat_id and message_id are not specified. Identifier of the inline message""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message.""" disable_web_page_preview: Optional[bool] = None diff --git a/aiogram/api/methods/send_animation.py b/aiogram/api/methods/send_animation.py index 27007d1b..aca62a40 100644 --- a/aiogram/api/methods/send_animation.py +++ b/aiogram/api/methods/send_animation.py @@ -1,6 +1,7 @@ from typing import Any, Dict, Optional, Union from ..types import ( + UNSET, ForceReply, InlineKeyboardMarkup, InputFile, @@ -45,7 +46,7 @@ class SendAnimation(TelegramMethod[Message]): caption: Optional[str] = None """Animation caption (may also be used when resending animation by file_id), 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" disable_notification: Optional[bool] = None diff --git a/aiogram/api/methods/send_audio.py b/aiogram/api/methods/send_audio.py index a67ca833..be4870c4 100644 --- a/aiogram/api/methods/send_audio.py +++ b/aiogram/api/methods/send_audio.py @@ -1,6 +1,7 @@ from typing import Any, Dict, Optional, Union from ..types import ( + UNSET, ForceReply, InlineKeyboardMarkup, InputFile, @@ -33,7 +34,7 @@ class SendAudio(TelegramMethod[Message]): file from the Internet, or upload a new one using multipart/form-data.""" caption: Optional[str] = None """Audio caption, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" duration: Optional[int] = None diff --git a/aiogram/api/methods/send_document.py b/aiogram/api/methods/send_document.py index 3c070539..c67588e4 100644 --- a/aiogram/api/methods/send_document.py +++ b/aiogram/api/methods/send_document.py @@ -1,6 +1,7 @@ from typing import Any, Dict, Optional, Union from ..types import ( + UNSET, ForceReply, InlineKeyboardMarkup, InputFile, @@ -39,7 +40,7 @@ class SendDocument(TelegramMethod[Message]): caption: Optional[str] = None """Document caption (may also be used when resending documents by file_id), 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" disable_notification: Optional[bool] = None diff --git a/aiogram/api/methods/send_message.py b/aiogram/api/methods/send_message.py index 849a1f5b..54f0fe37 100644 --- a/aiogram/api/methods/send_message.py +++ b/aiogram/api/methods/send_message.py @@ -1,6 +1,7 @@ from typing import Any, Dict, Optional, Union from ..types import ( + UNSET, ForceReply, InlineKeyboardMarkup, Message, @@ -24,7 +25,7 @@ class SendMessage(TelegramMethod[Message]): @channelusername)""" text: str """Text of the message to be sent, 1-4096 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message.""" disable_web_page_preview: Optional[bool] = None diff --git a/aiogram/api/methods/send_photo.py b/aiogram/api/methods/send_photo.py index 328b29b6..89a25864 100644 --- a/aiogram/api/methods/send_photo.py +++ b/aiogram/api/methods/send_photo.py @@ -1,6 +1,7 @@ from typing import Any, Dict, Optional, Union from ..types import ( + UNSET, ForceReply, InlineKeyboardMarkup, InputFile, @@ -30,7 +31,7 @@ class SendPhoto(TelegramMethod[Message]): caption: Optional[str] = None """Photo caption (may also be used when resending photos by file_id), 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" disable_notification: Optional[bool] = None diff --git a/aiogram/api/methods/send_video.py b/aiogram/api/methods/send_video.py index 07c4a3b6..f2659348 100644 --- a/aiogram/api/methods/send_video.py +++ b/aiogram/api/methods/send_video.py @@ -1,6 +1,7 @@ from typing import Any, Dict, Optional, Union from ..types import ( + UNSET, ForceReply, InlineKeyboardMarkup, InputFile, @@ -45,7 +46,7 @@ class SendVideo(TelegramMethod[Message]): caption: Optional[str] = None """Video caption (may also be used when resending videos by file_id), 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" supports_streaming: Optional[bool] = None diff --git a/aiogram/api/methods/send_voice.py b/aiogram/api/methods/send_voice.py index 17522782..1369ad1c 100644 --- a/aiogram/api/methods/send_voice.py +++ b/aiogram/api/methods/send_voice.py @@ -1,6 +1,7 @@ from typing import Any, Dict, Optional, Union from ..types import ( + UNSET, ForceReply, InlineKeyboardMarkup, InputFile, @@ -33,7 +34,7 @@ class SendVoice(TelegramMethod[Message]): Internet, or upload a new one using multipart/form-data.""" caption: Optional[str] = None """Voice message caption, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" duration: Optional[int] = None diff --git a/aiogram/api/types/__init__.py b/aiogram/api/types/__init__.py index 429b6f41..f8fd0fcd 100644 --- a/aiogram/api/types/__init__.py +++ b/aiogram/api/types/__init__.py @@ -1,6 +1,6 @@ from .animation import Animation from .audio import Audio -from .base import TelegramObject +from .base import UNSET, TelegramObject from .bot_command import BotCommand from .callback_game import CallbackGame from .callback_query import CallbackQuery @@ -101,6 +101,7 @@ from .webhook_info import WebhookInfo __all__ = ( "TelegramObject", + "UNSET", "BufferedInputFile", "FSInputFile", "Update", diff --git a/aiogram/api/types/base.py b/aiogram/api/types/base.py index 8c098202..06618234 100644 --- a/aiogram/api/types/base.py +++ b/aiogram/api/types/base.py @@ -1,4 +1,6 @@ import datetime +from typing import Any +from unittest.mock import sentinel from pydantic import BaseModel, Extra @@ -19,3 +21,7 @@ class TelegramObject(ContextInstanceMixin["TelegramObject"], BaseModel): class MutableTelegramObject(TelegramObject): class Config: allow_mutation = True + + +UNSET: Any = sentinel.UNSET # special sentinel object which used in sutuation when None might be a useful value +print(id(UNSET)) diff --git a/aiogram/api/types/inline_query_result_audio.py b/aiogram/api/types/inline_query_result_audio.py index c47104ba..687de9f0 100644 --- a/aiogram/api/types/inline_query_result_audio.py +++ b/aiogram/api/types/inline_query_result_audio.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -32,7 +33,7 @@ class InlineQueryResultAudio(InlineQueryResult): """Title""" caption: Optional[str] = None """Caption, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" performer: Optional[str] = None diff --git a/aiogram/api/types/inline_query_result_cached_audio.py b/aiogram/api/types/inline_query_result_cached_audio.py index 426ea462..af508b2e 100644 --- a/aiogram/api/types/inline_query_result_cached_audio.py +++ b/aiogram/api/types/inline_query_result_cached_audio.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -30,7 +31,7 @@ class InlineQueryResultCachedAudio(InlineQueryResult): """A valid file identifier for the audio file""" caption: Optional[str] = None """Caption, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/inline_query_result_cached_document.py b/aiogram/api/types/inline_query_result_cached_document.py index 27bcd27e..f9024291 100644 --- a/aiogram/api/types/inline_query_result_cached_document.py +++ b/aiogram/api/types/inline_query_result_cached_document.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -34,7 +35,7 @@ class InlineQueryResultCachedDocument(InlineQueryResult): """Short description of the result""" caption: Optional[str] = None """Caption of the document to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/inline_query_result_cached_gif.py b/aiogram/api/types/inline_query_result_cached_gif.py index 2b85bcd9..3408a404 100644 --- a/aiogram/api/types/inline_query_result_cached_gif.py +++ b/aiogram/api/types/inline_query_result_cached_gif.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -30,7 +31,7 @@ class InlineQueryResultCachedGif(InlineQueryResult): """Title for the result""" caption: Optional[str] = None """Caption of the GIF file to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/inline_query_result_cached_mpeg4_gif.py b/aiogram/api/types/inline_query_result_cached_mpeg4_gif.py index 5611e114..71a4e926 100644 --- a/aiogram/api/types/inline_query_result_cached_mpeg4_gif.py +++ b/aiogram/api/types/inline_query_result_cached_mpeg4_gif.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -31,7 +32,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult): """Title for the result""" caption: Optional[str] = None """Caption of the MPEG-4 file to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/inline_query_result_cached_photo.py b/aiogram/api/types/inline_query_result_cached_photo.py index da865bed..1e7abd57 100644 --- a/aiogram/api/types/inline_query_result_cached_photo.py +++ b/aiogram/api/types/inline_query_result_cached_photo.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -32,7 +33,7 @@ class InlineQueryResultCachedPhoto(InlineQueryResult): """Short description of the result""" caption: Optional[str] = None """Caption of the photo to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/inline_query_result_cached_video.py b/aiogram/api/types/inline_query_result_cached_video.py index db71f4f2..b6161679 100644 --- a/aiogram/api/types/inline_query_result_cached_video.py +++ b/aiogram/api/types/inline_query_result_cached_video.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -32,7 +33,7 @@ class InlineQueryResultCachedVideo(InlineQueryResult): """Short description of the result""" caption: Optional[str] = None """Caption of the video to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/inline_query_result_cached_voice.py b/aiogram/api/types/inline_query_result_cached_voice.py index 9d65b6fd..12491b88 100644 --- a/aiogram/api/types/inline_query_result_cached_voice.py +++ b/aiogram/api/types/inline_query_result_cached_voice.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -32,7 +33,7 @@ class InlineQueryResultCachedVoice(InlineQueryResult): """Voice message title""" caption: Optional[str] = None """Caption, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/inline_query_result_document.py b/aiogram/api/types/inline_query_result_document.py index 625b4675..0c66579c 100644 --- a/aiogram/api/types/inline_query_result_document.py +++ b/aiogram/api/types/inline_query_result_document.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -35,7 +36,7 @@ class InlineQueryResultDocument(InlineQueryResult): """Mime type of the content of the file, either 'application/pdf' or 'application/zip'""" caption: Optional[str] = None """Caption of the document to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" description: Optional[str] = None diff --git a/aiogram/api/types/inline_query_result_gif.py b/aiogram/api/types/inline_query_result_gif.py index ffaa7a66..1285b96f 100644 --- a/aiogram/api/types/inline_query_result_gif.py +++ b/aiogram/api/types/inline_query_result_gif.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -38,7 +39,7 @@ class InlineQueryResultGif(InlineQueryResult): """Title for the result""" caption: Optional[str] = None """Caption of the GIF file to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/inline_query_result_mpeg4_gif.py b/aiogram/api/types/inline_query_result_mpeg4_gif.py index 59d1ef01..4fa6a8e9 100644 --- a/aiogram/api/types/inline_query_result_mpeg4_gif.py +++ b/aiogram/api/types/inline_query_result_mpeg4_gif.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -39,7 +40,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult): """Title for the result""" caption: Optional[str] = None """Caption of the MPEG-4 file to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/inline_query_result_photo.py b/aiogram/api/types/inline_query_result_photo.py index 7ee7e4f5..5927c62c 100644 --- a/aiogram/api/types/inline_query_result_photo.py +++ b/aiogram/api/types/inline_query_result_photo.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -38,7 +39,7 @@ class InlineQueryResultPhoto(InlineQueryResult): """Short description of the result""" caption: Optional[str] = None """Caption of the photo to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/inline_query_result_video.py b/aiogram/api/types/inline_query_result_video.py index a0010fea..5ea390ed 100644 --- a/aiogram/api/types/inline_query_result_video.py +++ b/aiogram/api/types/inline_query_result_video.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -36,7 +37,7 @@ class InlineQueryResultVideo(InlineQueryResult): """Title for the result""" caption: Optional[str] = None """Caption of the video to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" video_width: Optional[int] = None diff --git a/aiogram/api/types/inline_query_result_voice.py b/aiogram/api/types/inline_query_result_voice.py index b4b10f4f..74d17448 100644 --- a/aiogram/api/types/inline_query_result_voice.py +++ b/aiogram/api/types/inline_query_result_voice.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from .base import UNSET from .inline_query_result import InlineQueryResult if TYPE_CHECKING: # pragma: no cover @@ -33,7 +34,7 @@ class InlineQueryResultVoice(InlineQueryResult): """Recording title""" caption: Optional[str] = None """Caption, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" voice_duration: Optional[int] = None diff --git a/aiogram/api/types/input_media_animation.py b/aiogram/api/types/input_media_animation.py index de994e85..e62dc95e 100644 --- a/aiogram/api/types/input_media_animation.py +++ b/aiogram/api/types/input_media_animation.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional, Union from pydantic import Field +from .base import UNSET from .input_media import InputMedia if TYPE_CHECKING: # pragma: no cover @@ -33,7 +34,7 @@ class InputMediaAnimation(InputMedia): multipart/form-data under .""" caption: Optional[str] = None """Caption of the animation to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" width: Optional[int] = None diff --git a/aiogram/api/types/input_media_audio.py b/aiogram/api/types/input_media_audio.py index 9d700101..40059bd9 100644 --- a/aiogram/api/types/input_media_audio.py +++ b/aiogram/api/types/input_media_audio.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional, Union from pydantic import Field +from .base import UNSET from .input_media import InputMedia if TYPE_CHECKING: # pragma: no cover @@ -33,7 +34,7 @@ class InputMediaAudio(InputMedia): multipart/form-data under .""" caption: Optional[str] = None """Caption of the audio to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" duration: Optional[int] = None diff --git a/aiogram/api/types/input_media_document.py b/aiogram/api/types/input_media_document.py index 5f95b233..d57f1178 100644 --- a/aiogram/api/types/input_media_document.py +++ b/aiogram/api/types/input_media_document.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional, Union from pydantic import Field +from .base import UNSET from .input_media import InputMedia if TYPE_CHECKING: # pragma: no cover @@ -33,6 +34,6 @@ class InputMediaDocument(InputMedia): multipart/form-data under .""" caption: Optional[str] = None """Caption of the document to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" diff --git a/aiogram/api/types/input_media_photo.py b/aiogram/api/types/input_media_photo.py index 7698d95d..c92b45e4 100644 --- a/aiogram/api/types/input_media_photo.py +++ b/aiogram/api/types/input_media_photo.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional, Union from pydantic import Field +from .base import UNSET from .input_media import InputMedia if TYPE_CHECKING: # pragma: no cover @@ -26,6 +27,6 @@ class InputMediaPhoto(InputMedia): name.""" caption: Optional[str] = None """Caption of the photo to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" diff --git a/aiogram/api/types/input_media_video.py b/aiogram/api/types/input_media_video.py index a0cdd46f..61e73c1e 100644 --- a/aiogram/api/types/input_media_video.py +++ b/aiogram/api/types/input_media_video.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional, Union from pydantic import Field +from .base import UNSET from .input_media import InputMedia if TYPE_CHECKING: # pragma: no cover @@ -33,7 +34,7 @@ class InputMediaVideo(InputMedia): multipart/form-data under .""" caption: Optional[str] = None """Caption of the video to be sent, 0-1024 characters after entities parsing""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.""" width: Optional[int] = None diff --git a/aiogram/api/types/input_text_message_content.py b/aiogram/api/types/input_text_message_content.py index ff3ef5d9..3c5bda13 100644 --- a/aiogram/api/types/input_text_message_content.py +++ b/aiogram/api/types/input_text_message_content.py @@ -2,6 +2,7 @@ from __future__ import annotations from typing import Optional +from .base import UNSET from .input_message_content import InputMessageContent @@ -14,7 +15,7 @@ class InputTextMessageContent(InputMessageContent): message_text: str """Text of the message to be sent, 1-4096 characters""" - parse_mode: Optional[str] = None + parse_mode: Optional[str] = UNSET """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message.""" disable_web_page_preview: Optional[bool] = None diff --git a/tests/test_api/test_methods/test_base.py b/tests/test_api/test_methods/test_base.py index c32a075b..e3627d54 100644 --- a/tests/test_api/test_methods/test_base.py +++ b/tests/test_api/test_methods/test_base.py @@ -59,4 +59,4 @@ class TestPrepareParseMode: def test_bot_not_in_context(self): data = {} prepare_parse_mode(data) - assert "parse_mode" not in data + assert data["parse_mode"] is None From 9f11afda5b94e744f5584e144410312011c73844 Mon Sep 17 00:00:00 2001 From: lyteloli <41185217+lyteloli@users.noreply.github.com> Date: Fri, 29 May 2020 22:28:12 +0300 Subject: [PATCH 02/11] Added fields to ChatMember (#340) * Added fields to ChatMember * Added ChatMemberStatus helper --- aiogram/api/types/chat_member.py | 23 +++++++++++++ docs/api/types/chat_member.md | 21 ++++++++++++ tests/test_api/test_types/test_chat_member.py | 34 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 tests/test_api/test_types/test_chat_member.py diff --git a/aiogram/api/types/chat_member.py b/aiogram/api/types/chat_member.py index 58aa7630..593a86fb 100644 --- a/aiogram/api/types/chat_member.py +++ b/aiogram/api/types/chat_member.py @@ -4,6 +4,7 @@ import datetime from typing import TYPE_CHECKING, Optional, Union from .base import TelegramObject +from ...utils import helper if TYPE_CHECKING: # pragma: no cover from .user import User @@ -65,3 +66,25 @@ class ChatMember(TelegramObject): inline bots""" can_add_web_page_previews: Optional[bool] = None """Restricted only. True, if the user is allowed to add web page previews to their messages""" + + @property + def is_chat_admin(self) -> bool: + return self.status in {ChatMemberStatus.CREATOR, ChatMemberStatus.ADMINISTRATOR} + + @property + def is_chat_member(self) -> bool: + return self.status not in {ChatMemberStatus.LEFT, ChatMemberStatus.KICKED} + + +class ChatMemberStatus(helper.Helper): + """ + Chat member status + """ + mode = helper.HelperMode.lowercase + + CREATOR = helper.Item() # creator + ADMINISTRATOR = helper.Item() # administrator + MEMBER = helper.Item() # member + RESTRICTED = helper.Item() # restricted + LEFT = helper.Item() # left + KICKED = helper.Item() # kicked diff --git a/docs/api/types/chat_member.md b/docs/api/types/chat_member.md index 0d374b01..809f8296 100644 --- a/docs/api/types/chat_member.md +++ b/docs/api/types/chat_member.md @@ -30,12 +30,33 @@ This object contains information about one member of a chat. | `can_add_web_page_previews` | `#!python Optional[bool]` | Optional. Restricted only. True, if the user is allowed to add web page previews to their messages | +## Extensions + +| Name | Type | Description | +| - | - | - | +| `is_chat_admin` | `#!python bool` | True if the user is administrator or creator of the chat | +| `is_chat_member` | `#!python bool` | True if the user is member of the chat | + + +## ChatMemberStatus helper + +This object helps to describe user's status. + +#### Attributes: +- CREATOR +- ADMINISTRATOR +- MEMBER +- RESTRICTED +- LEFT +- KICKED + ## Location - `from aiogram.types import ChatMember` - `from aiogram.api.types import ChatMember` - `from aiogram.api.types.chat_member import ChatMember` +- `from aiogram.api.types.chat_member import ChatMemberStatus` ## Related pages: diff --git a/tests/test_api/test_types/test_chat_member.py b/tests/test_api/test_types/test_chat_member.py new file mode 100644 index 00000000..e5706e5e --- /dev/null +++ b/tests/test_api/test_types/test_chat_member.py @@ -0,0 +1,34 @@ +import pytest + +from aiogram.api.types import ChatMember, User + +user = User(id=42, is_bot=False, first_name="User", last_name=None) + + +class TestChatMember: + @pytest.mark.parametrize( + "status,result", + [ + ["administrator", True], + ["creator", True], + ["member", False] + ] + ) + def test_is_chat_admin(self, status: str, result: bool): + chat_member = ChatMember(user=user, status=status) + assert chat_member.is_chat_admin == result + + @pytest.mark.parametrize( + "status,result", + [ + ["administrator", True], + ["creator", True], + ["member", True], + ["restricted", True], + ["kicked", False], + ["left", False] + ] + ) + def test_is_chat_member(self, status: str, result: bool): + chat_member = ChatMember(user=user, status=status) + assert chat_member.is_chat_member == result From aed36423852b963ffafa71bbe536de0963eacceb Mon Sep 17 00:00:00 2001 From: Martin Winks <50446230+uwinx@users.noreply.github.com> Date: Sun, 31 May 2020 19:01:28 +0400 Subject: [PATCH 03/11] feat(helpers): implement new descriptor with default value getter (#336) * feat(helpers): implement new descriptor with default value getter * perf(descriptor): use weakref refuse weak reference to a value in WeakRefDict instead of polluting instance namespace * chore(descriptor): rename descriptor class rename `DefaultProperty` to `Default` * style(fmt): lint code --- aiogram/api/client/session/base.py | 46 ++------------- aiogram/utils/helper.py | 58 ++++++++++++++++++- .../test_session/test_base_session.py | 9 +-- tests/test_utils/test_helper.py | 49 +++++++++++++++- 4 files changed, 112 insertions(+), 50 deletions(-) diff --git a/aiogram/api/client/session/base.py b/aiogram/api/client/session/base.py index 8213e4c3..379e69ac 100644 --- a/aiogram/api/client/session/base.py +++ b/aiogram/api/client/session/base.py @@ -8,6 +8,7 @@ from typing import Any, AsyncGenerator, Callable, ClassVar, Optional, Type, Type from aiogram.utils.exceptions import TelegramAPIError +from ....utils.helper import Default from ...methods import Response, TelegramMethod from ..telegram import PRODUCTION, TelegramAPIServer @@ -20,47 +21,10 @@ class BaseSession(abc.ABC): # global session timeout default_timeout: ClassVar[float] = 60.0 - _api: TelegramAPIServer - _json_loads: _JsonLoads - _json_dumps: _JsonDumps - _timeout: float - - @property - def api(self) -> TelegramAPIServer: - return getattr(self, "_api", PRODUCTION) # type: ignore - - @api.setter - def api(self, value: TelegramAPIServer) -> None: - self._api = value - - @property - def json_loads(self) -> _JsonLoads: - return getattr(self, "_json_loads", json.loads) # type: ignore - - @json_loads.setter - def json_loads(self, value: _JsonLoads) -> None: - self._json_loads = value # type: ignore - - @property - def json_dumps(self) -> _JsonDumps: - return getattr(self, "_json_dumps", json.dumps) # type: ignore - - @json_dumps.setter - def json_dumps(self, value: _JsonDumps) -> None: - self._json_dumps = value # type: ignore - - @property - def timeout(self) -> float: - return getattr(self, "_timeout", self.__class__.default_timeout) # type: ignore - - @timeout.setter - def timeout(self, value: float) -> None: - self._timeout = value - - @timeout.deleter - def timeout(self) -> None: - if hasattr(self, "_timeout"): - del self._timeout + api: Default[TelegramAPIServer] = Default(PRODUCTION) + json_loads: Default[_JsonLoads] = Default(json.loads) + json_dumps: Default[_JsonDumps] = Default(json.dumps) + timeout: Default[float] = Default(fget=lambda self: float(self.__class__.default_timeout)) @classmethod def raise_for_status(cls, response: Response[T]) -> None: diff --git a/aiogram/utils/helper.py b/aiogram/utils/helper.py index e582a4f0..57f4e76e 100644 --- a/aiogram/utils/helper.py +++ b/aiogram/utils/helper.py @@ -14,7 +14,10 @@ Example: <<< ['barItem', 'bazItem', 'fooItem', 'lorem'] """ import inspect -from typing import Any, Callable, Iterable, List, Optional, Union, cast +from typing import Any, Callable, Generic, Iterable, List, Optional, TypeVar, Union, cast +from weakref import WeakKeyDictionary + +T = TypeVar("T") PROPS_KEYS_ATTR_NAME = "_props_keys" @@ -233,3 +236,56 @@ class OrderedHelper(Helper, metaclass=OrderedHelperMeta): else: result.append(value) return result + + +class Default(Generic[T]): + """ + Descriptor that holds default value getter + + Example: + >>> class MyClass: + ... att = Default("dflt") + ... + >>> my_instance = MyClass() + >>> my_instance.att = "not dflt" + >>> my_instance.att + 'not dflt' + >>> MyClass.att + 'dflt' + >>> del my_instance.att + >>> my_instance.att + 'dflt' + >>> + + Intended to be used as a class attribute and only internally. + """ + + __slots__ = "fget", "_descriptor_instances" + + def __init__( + self, default: Optional[T] = None, *, fget: Optional[Callable[[Any], T]] = None, + ) -> None: + self.fget = fget or (lambda _: cast(T, default)) + self._descriptor_instances = WeakKeyDictionary() # type: ignore + + def __get__(self, instance: Any, owner: Any) -> T: + if instance is None: + return self.fget(instance) + + return self._descriptor_instances.get(instance, self.fget(instance)) + + def __set__(self, instance: Any, value: T) -> None: + if instance is None or isinstance(instance, type): + raise AttributeError( + "Instance cannot be class or None. Setter must be called from a class." + ) + + self._descriptor_instances[instance] = value + + def __delete__(self, instance: Any) -> None: + if instance is None or isinstance(instance, type): + raise AttributeError( + "Instance cannot be class or None. Deleter must be called from a class." + ) + + self._descriptor_instances.pop(instance, None) diff --git a/tests/test_api/test_client/test_session/test_base_session.py b/tests/test_api/test_client/test_session/test_base_session.py index 35dcfa8e..3ac1254b 100644 --- a/tests/test_api/test_client/test_session/test_base_session.py +++ b/tests/test_api/test_client/test_session/test_base_session.py @@ -49,14 +49,9 @@ class TestBaseSession: return json.dumps session.json_dumps = custom_dumps - assert session.json_dumps == custom_dumps == session._json_dumps + assert session.json_dumps == custom_dumps session.json_loads = custom_loads - assert session.json_loads == custom_loads == session._json_loads - - different_session = CustomSession() - assert all( - not hasattr(different_session, attr) for attr in ("_json_loads", "_json_dumps", "_api") - ) + assert session.json_loads == custom_loads def test_timeout(self): session = CustomSession() diff --git a/tests/test_utils/test_helper.py b/tests/test_utils/test_helper.py index 8125ef60..466db4ef 100644 --- a/tests/test_utils/test_helper.py +++ b/tests/test_utils/test_helper.py @@ -1,6 +1,6 @@ import pytest -from aiogram.utils.helper import Helper, HelperMode, Item, ListItem, OrderedHelper +from aiogram.utils.helper import Default, Helper, HelperMode, Item, ListItem, OrderedHelper class TestHelper: @@ -132,3 +132,50 @@ class TestOrderedHelper: B = ListItem() assert MyOrderedHelper.all() == ["A", "D", "C", "B"] + + +class TestDefaultDescriptor: + def test_descriptor_fs(self): + obj = type("ClassA", (), {})() + default_x_val = "some_x" + x = Default(default_x_val) + + # we can omit owner, usually it's just obj.__class__ + assert x.__get__(instance=obj, owner=None) == default_x_val + assert x.__get__(instance=obj, owner=obj.__class__) == default_x_val + + new_x_val = "new_x" + assert x.__set__(instance=obj, value=new_x_val) is None + + with pytest.raises(AttributeError) as exc: + x.__set__(instance=obj.__class__, value="will never be set") + assert "Instance cannot be class or None" in str(exc.value) + + assert x.__get__(instance=obj, owner=obj.__class__) == new_x_val + + with pytest.raises(AttributeError) as exc: + x.__delete__(instance=obj.__class__) + assert "Instance cannot be class or None" in str(exc.value) + + x.__delete__(instance=obj) + assert x.__get__(instance=obj, owner=obj.__class__) == default_x_val + + def test_init(self): + class A: + x = Default(fget=lambda a_inst: "nothing") + + assert isinstance(A.__dict__["x"], Default) + + a = A() + assert a.x == "nothing" + + x = Default("x") + assert x.__get__(None, None) == "x" + assert x.fget(None) == x.__get__(None, None) + + def test_nullability(self): + class A: + x = Default(default=None, fget=None) + + assert A.x is None + assert A().x is None From 87104bd783990ca2c47d3aae3d1d461ddbbea750 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sun, 31 May 2020 18:27:47 +0300 Subject: [PATCH 04/11] Fix pipeline warning --- .github/workflows/tests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5e252c62..6061286a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -49,6 +49,5 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} file: coverage.xml flags: unittests - yml: codecov.yml name: py-${{ matrix.python-version }}-${{ matrix.os }} fail_ci_if_error: true From 7844a663a983a599c79a6bee06fcb5a4323fc0b3 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sun, 14 Jun 2020 17:14:10 +0300 Subject: [PATCH 05/11] Bump Telegram Bot API version Change request timeout mechanism Bump package version --- .apiversion | 2 +- aiogram/__init__.py | 4 +- aiogram/api/client/bot.py | 434 ++++++++++++------ aiogram/api/client/session/aiohttp.py | 8 +- aiogram/api/client/session/base.py | 7 +- aiogram/api/methods/answer_inline_query.py | 4 +- aiogram/api/methods/base.py | 4 - aiogram/api/methods/edit_message_caption.py | 3 +- aiogram/api/methods/edit_message_text.py | 3 +- aiogram/api/methods/pin_chat_message.py | 4 +- aiogram/api/methods/send_animation.py | 8 +- aiogram/api/methods/send_audio.py | 7 +- aiogram/api/methods/send_dice.py | 9 +- aiogram/api/methods/send_document.py | 7 +- aiogram/api/methods/send_game.py | 2 +- aiogram/api/methods/send_message.py | 3 +- aiogram/api/methods/send_photo.py | 3 +- aiogram/api/methods/send_video.py | 7 +- aiogram/api/methods/send_video_note.py | 4 +- aiogram/api/methods/send_voice.py | 4 +- aiogram/api/methods/set_webhook.py | 6 +- aiogram/api/methods/unpin_chat_message.py | 4 +- aiogram/api/types/base.py | 1 - aiogram/api/types/chat_member.py | 3 +- aiogram/api/types/dice.py | 6 +- aiogram/api/types/force_reply.py | 16 +- aiogram/api/types/game_high_score.py | 2 +- aiogram/api/types/inline_keyboard_button.py | 8 +- .../api/types/inline_query_result_audio.py | 3 +- .../types/inline_query_result_cached_audio.py | 3 +- .../inline_query_result_cached_document.py | 3 +- .../types/inline_query_result_cached_gif.py | 3 +- .../inline_query_result_cached_mpeg4_gif.py | 3 +- .../types/inline_query_result_cached_photo.py | 3 +- .../types/inline_query_result_cached_video.py | 3 +- .../types/inline_query_result_cached_voice.py | 4 +- .../api/types/inline_query_result_document.py | 3 +- aiogram/api/types/inline_query_result_gif.py | 8 +- .../types/inline_query_result_mpeg4_gif.py | 8 +- .../api/types/inline_query_result_photo.py | 3 +- .../api/types/inline_query_result_video.py | 3 +- .../api/types/inline_query_result_voice.py | 4 +- aiogram/api/types/input_media_animation.py | 8 +- aiogram/api/types/input_media_audio.py | 7 +- aiogram/api/types/input_media_document.py | 7 +- aiogram/api/types/input_media_photo.py | 3 +- aiogram/api/types/input_media_video.py | 7 +- .../api/types/input_text_message_content.py | 3 +- aiogram/api/types/message.py | 43 +- aiogram/api/types/update.py | 4 +- aiogram/api/types/user.py | 6 +- docs/_api_version.md | 2 +- docs/_package_version.md | 2 +- poetry.lock | 153 +++--- pyproject.toml | 2 +- tests/mocked_bot.py | 5 +- .../test_session/test_base_session.py | 5 +- tests/test_api/test_types/test_chat_member.py | 11 +- 58 files changed, 526 insertions(+), 369 deletions(-) diff --git a/.apiversion b/.apiversion index b6afe802..899dd4f5 100644 --- a/.apiversion +++ b/.apiversion @@ -1 +1 @@ -4.8 \ No newline at end of file +4.9 \ No newline at end of file diff --git a/aiogram/__init__.py b/aiogram/__init__.py index 0b2a8cc7..435b4eaf 100644 --- a/aiogram/__init__.py +++ b/aiogram/__init__.py @@ -28,5 +28,5 @@ __all__ = ( "handler", ) -__version__ = "3.0.0a4" -__api_version__ = "4.8" +__version__ = "3.0.0a5" +__api_version__ = "4.9" diff --git a/aiogram/api/client/bot.py b/aiogram/api/client/bot.py index 0d2bf1d9..673356d9 100644 --- a/aiogram/api/client/bot.py +++ b/aiogram/api/client/bot.py @@ -269,7 +269,9 @@ class Bot(ContextInstanceMixin["Bot"]): file_path, destination=destination, timeout=timeout, chunk_size=chunk_size, seek=seek ) - async def __call__(self, method: TelegramMethod[T]) -> T: + async def __call__( + self, method: TelegramMethod[T], request_timeout: Optional[int] = None + ) -> T: """ Call API method @@ -308,6 +310,7 @@ class Bot(ContextInstanceMixin["Bot"]): limit: Optional[int] = None, timeout: Optional[int] = None, allowed_updates: Optional[List[str]] = None, + request_timeout: Optional[int] = None, ) -> List[Update]: """ Use this method to receive incoming updates using long polling (wiki). An Array of Update @@ -337,12 +340,13 @@ class Bot(ContextInstanceMixin["Bot"]): Update for a complete list of available update types. Specify an empty list to receive all updates regardless of type (default). If not specified, the previous setting will be used. + :param request_timeout: Request timeout :return: An Array of Update objects is returned. """ call = GetUpdates( offset=offset, limit=limit, timeout=timeout, allowed_updates=allowed_updates, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def set_webhook( self, @@ -350,6 +354,7 @@ class Bot(ContextInstanceMixin["Bot"]): certificate: Optional[InputFile] = None, max_connections: Optional[int] = None, allowed_updates: Optional[List[str]] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to specify a url and receive incoming updates via an outgoing webhook. @@ -358,7 +363,7 @@ class Bot(ContextInstanceMixin["Bot"]): will give up after a reasonable amount of attempts. Returns True on success. If you'd like to make sure that the Webhook request comes from Telegram, we recommend using a secret path in the URL, e.g. https://www.example.com/. Since nobody else - knows your bot‘s token, you can be pretty sure it’s us. + knows your bot's token, you can be pretty sure it's us. Notes 1. You will not be able to receive updates using getUpdates for as long as an outgoing webhook is set up. @@ -376,14 +381,15 @@ class Bot(ContextInstanceMixin["Bot"]): can be checked. See our self-signed guide for details. :param max_connections: Maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery, 1-100. Defaults to 40. Use lower - values to limit the load on your bot‘s server, and higher values - to increase your bot’s throughput. + values to limit the load on your bot's server, and higher values + to increase your bot's throughput. :param allowed_updates: A JSON-serialized list of the update types you want your bot to receive. For example, specify ['message', 'edited_channel_post', 'callback_query'] to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all updates regardless of type (default). If not specified, the previous setting will be used. + :param request_timeout: Request timeout :return: Returns True on success. """ call = SetWebhook( @@ -392,21 +398,22 @@ class Bot(ContextInstanceMixin["Bot"]): max_connections=max_connections, allowed_updates=allowed_updates, ) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def delete_webhook(self,) -> bool: + async def delete_webhook(self, request_timeout: Optional[int] = None,) -> bool: """ Use this method to remove webhook integration if you decide to switch back to getUpdates. Returns True on success. Requires no parameters. Source: https://core.telegram.org/bots/api#deletewebhook + :param request_timeout: Request timeout :return: Returns True on success. """ call = DeleteWebhook() - return await self(call) + return await self(call, request_timeout=request_timeout) - async def get_webhook_info(self,) -> WebhookInfo: + async def get_webhook_info(self, request_timeout: Optional[int] = None,) -> WebhookInfo: """ Use this method to get current webhook status. Requires no parameters. On success, returns a WebhookInfo object. If the bot is using getUpdates, will return an object with the url @@ -414,28 +421,30 @@ class Bot(ContextInstanceMixin["Bot"]): Source: https://core.telegram.org/bots/api#getwebhookinfo + :param request_timeout: Request timeout :return: On success, returns a WebhookInfo object. If the bot is using getUpdates, will return an object with the url field empty. """ call = GetWebhookInfo() - return await self(call) + return await self(call, request_timeout=request_timeout) # ============================================================================================= # Group: Available methods # Source: https://core.telegram.org/bots/api#available-methods # ============================================================================================= - async def get_me(self,) -> User: + async def get_me(self, request_timeout: Optional[int] = None,) -> User: """ A simple method for testing your bot's auth token. Requires no parameters. Returns basic information about the bot in form of a User object. Source: https://core.telegram.org/bots/api#getme + :param request_timeout: Request timeout :return: Returns basic information about the bot in form of a User object. """ call = GetMe() - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_message( self, @@ -448,6 +457,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send text messages. On success, the sent Message is returned. @@ -466,6 +476,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendMessage( @@ -477,7 +488,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def forward_message( self, @@ -485,6 +496,7 @@ class Bot(ContextInstanceMixin["Bot"]): from_chat_id: Union[int, str], message_id: int, disable_notification: Optional[bool] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to forward messages of any kind. On success, the sent Message is returned. @@ -498,6 +510,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param message_id: Message identifier in the chat specified in from_chat_id :param disable_notification: Sends the message silently. Users will receive a notification with no sound. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = ForwardMessage( @@ -506,7 +519,7 @@ class Bot(ContextInstanceMixin["Bot"]): message_id=message_id, disable_notification=disable_notification, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_photo( self, @@ -519,6 +532,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -541,6 +555,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendPhoto( @@ -552,7 +567,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_audio( self, @@ -569,6 +584,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send audio files, if you want Telegram clients to display them in the @@ -593,9 +609,9 @@ class Bot(ContextInstanceMixin["Bot"]): :param title: Track name :param thumb: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and - less than 200 kB in size. A thumbnail‘s width and height should not exceed + less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. - Thumbnails can’t be reused and can be only uploaded as a new file, so you + Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under . :param disable_notification: Sends the message silently. Users will receive a notification @@ -604,6 +620,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendAudio( @@ -619,7 +636,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_document( self, @@ -633,6 +650,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send general files. On success, the sent Message is returned. Bots can @@ -649,9 +667,9 @@ class Bot(ContextInstanceMixin["Bot"]): multipart/form-data. :param thumb: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and - less than 200 kB in size. A thumbnail‘s width and height should not exceed + less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. - Thumbnails can’t be reused and can be only uploaded as a new file, so you + Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under . :param caption: Document caption (may also be used when resending documents by file_id), @@ -664,6 +682,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendDocument( @@ -676,7 +695,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_video( self, @@ -694,6 +713,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats @@ -713,9 +733,9 @@ class Bot(ContextInstanceMixin["Bot"]): :param height: Video height :param thumb: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and - less than 200 kB in size. A thumbnail‘s width and height should not exceed + less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. - Thumbnails can’t be reused and can be only uploaded as a new file, so you + Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under . :param caption: Video caption (may also be used when resending videos by file_id), 0-1024 @@ -729,6 +749,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendVideo( @@ -745,7 +766,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_animation( self, @@ -762,6 +783,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On @@ -781,9 +803,9 @@ class Bot(ContextInstanceMixin["Bot"]): :param height: Animation height :param thumb: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and - less than 200 kB in size. A thumbnail‘s width and height should not exceed + less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. - Thumbnails can’t be reused and can be only uploaded as a new file, so you + Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under . :param caption: Animation caption (may also be used when resending animation by file_id), @@ -796,6 +818,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendAnimation( @@ -811,7 +834,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_voice( self, @@ -825,6 +848,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a @@ -851,6 +875,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendVoice( @@ -863,7 +888,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_video_note( self, @@ -877,6 +902,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute long. @@ -894,9 +920,9 @@ class Bot(ContextInstanceMixin["Bot"]): :param length: Video width and height, i.e. diameter of the video message :param thumb: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and - less than 200 kB in size. A thumbnail‘s width and height should not exceed + less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. - Thumbnails can’t be reused and can be only uploaded as a new file, so you + Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under . :param disable_notification: Sends the message silently. Users will receive a notification @@ -905,6 +931,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendVideoNote( @@ -917,7 +944,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_media_group( self, @@ -925,6 +952,7 @@ class Bot(ContextInstanceMixin["Bot"]): media: List[Union[InputMediaPhoto, InputMediaVideo]], disable_notification: Optional[bool] = None, reply_to_message_id: Optional[int] = None, + request_timeout: Optional[int] = None, ) -> List[Message]: """ Use this method to send a group of photos or videos as an album. On success, an array of @@ -939,6 +967,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param disable_notification: Sends the messages silently. Users will receive a notification with no sound. :param reply_to_message_id: If the messages are a reply, ID of the original message + :param request_timeout: Request timeout :return: On success, an array of the sent Messages is returned. """ call = SendMediaGroup( @@ -947,7 +976,7 @@ class Bot(ContextInstanceMixin["Bot"]): disable_notification=disable_notification, reply_to_message_id=reply_to_message_id, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_location( self, @@ -960,6 +989,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -978,6 +1008,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendLocation( @@ -989,7 +1020,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def edit_message_live_location( self, @@ -999,6 +1030,7 @@ class Bot(ContextInstanceMixin["Bot"]): message_id: Optional[int] = None, inline_message_id: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + request_timeout: Optional[int] = None, ) -> Union[Message, bool]: """ Use this method to edit live location messages. A location can be edited until its @@ -1018,6 +1050,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param inline_message_id: Required if chat_id and message_id are not specified. Identifier of the inline message :param reply_markup: A JSON-serialized object for a new inline keyboard. + :param request_timeout: Request timeout :return: On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned. """ @@ -1029,7 +1062,7 @@ class Bot(ContextInstanceMixin["Bot"]): inline_message_id=inline_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def stop_message_live_location( self, @@ -1037,6 +1070,7 @@ class Bot(ContextInstanceMixin["Bot"]): message_id: Optional[int] = None, inline_message_id: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + request_timeout: Optional[int] = None, ) -> Union[Message, bool]: """ Use this method to stop updating a live location message before live_period expires. On @@ -1053,6 +1087,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param inline_message_id: Required if chat_id and message_id are not specified. Identifier of the inline message :param reply_markup: A JSON-serialized object for a new inline keyboard. + :param request_timeout: Request timeout :return: On success, if the message was sent by the bot, the sent Message is returned, otherwise True is returned. """ @@ -1062,7 +1097,7 @@ class Bot(ContextInstanceMixin["Bot"]): inline_message_id=inline_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_venue( self, @@ -1078,6 +1113,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send information about a venue. On success, the sent Message is @@ -1101,6 +1137,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendVenue( @@ -1115,7 +1152,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_contact( self, @@ -1129,6 +1166,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -1147,6 +1185,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendContact( @@ -1159,7 +1198,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_poll( self, @@ -1180,6 +1219,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send a native poll. On success, the sent Message is returned. @@ -1215,6 +1255,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendPoll( @@ -1234,7 +1275,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def send_dice( self, @@ -1245,24 +1286,26 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ - Use this method to send a dice, which will have a random value from 1 to 6. On success, - the sent Message is returned. (Yes, we're aware of the 'proper' singular of die. But it's - awkward, and we decided to help it change. One dice at a time!) + Use this method to send an animated emoji that will display a random value. On success, + the sent Message is returned. Source: https://core.telegram.org/bots/api#senddice :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :param emoji: Emoji on which the dice throw animation is based. Currently, must be one of - '' or ''. Defauts to '' + '', '', or ''. Dice can have values 1-6 for '' and '', and values 1-5 for + ''. Defaults to '' :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :param reply_to_message_id: If the message is a reply, ID of the original message :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendDice( @@ -1272,9 +1315,11 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def send_chat_action(self, chat_id: Union[int, str], action: str,) -> bool: + async def send_chat_action( + self, chat_id: Union[int, str], action: str, request_timeout: Optional[int] = None, + ) -> bool: """ Use this method when you need to tell the user that something is happening on the bot's side. The status is set for 5 seconds or less (when a message arrives from your bot, @@ -1295,13 +1340,18 @@ class Bot(ContextInstanceMixin["Bot"]): record_video or upload_video for videos, record_audio or upload_audio for audio files, upload_document for general files, find_location for location data, record_video_note or upload_video_note for video notes. + :param request_timeout: Request timeout :return: Returns True on success. """ call = SendChatAction(chat_id=chat_id, action=action,) - return await self(call) + return await self(call, request_timeout=request_timeout) async def get_user_profile_photos( - self, user_id: int, offset: Optional[int] = None, limit: Optional[int] = None, + self, + user_id: int, + offset: Optional[int] = None, + limit: Optional[int] = None, + request_timeout: Optional[int] = None, ) -> UserProfilePhotos: """ Use this method to get a list of profile pictures for a user. Returns a UserProfilePhotos @@ -1314,12 +1364,13 @@ class Bot(ContextInstanceMixin["Bot"]): are returned. :param limit: Limits the number of photos to be retrieved. Values between 1-100 are accepted. Defaults to 100. + :param request_timeout: Request timeout :return: Returns a UserProfilePhotos object. """ call = GetUserProfilePhotos(user_id=user_id, offset=offset, limit=limit,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def get_file(self, file_id: str,) -> File: + async def get_file(self, file_id: str, request_timeout: Optional[int] = None,) -> File: """ Use this method to get basic info about a file and prepare it for downloading. For the moment, bots can download files of up to 20MB in size. On success, a File object is @@ -1333,16 +1384,18 @@ class Bot(ContextInstanceMixin["Bot"]): Source: https://core.telegram.org/bots/api#getfile :param file_id: File identifier to get info about + :param request_timeout: Request timeout :return: On success, a File object is returned. """ call = GetFile(file_id=file_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) async def kick_chat_member( self, chat_id: Union[int, str], user_id: int, until_date: Optional[Union[datetime.datetime, datetime.timedelta, int]] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to kick a user from a group, a supergroup or a channel. In the case of @@ -1358,13 +1411,16 @@ class Bot(ContextInstanceMixin["Bot"]): :param until_date: Date when the user will be unbanned, unix time. If user is banned for more than 366 days or less than 30 seconds from the current time they are considered to be banned forever + :param request_timeout: Request timeout :return: In the case of supergroups and channels, the user will not be able to return to the group on their own using invite links, etc. Returns True on success. """ call = KickChatMember(chat_id=chat_id, user_id=user_id, until_date=until_date,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def unban_chat_member(self, chat_id: Union[int, str], user_id: int,) -> bool: + async def unban_chat_member( + self, chat_id: Union[int, str], user_id: int, request_timeout: Optional[int] = None, + ) -> bool: """ Use this method to unban a previously kicked user in a supergroup or channel. The user will not return to the group or channel automatically, but will be able to join via link, @@ -1375,11 +1431,12 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target group or username of the target supergroup or channel (in the format @username) :param user_id: Unique identifier of the target user + :param request_timeout: Request timeout :return: The user will not return to the group or channel automatically, but will be able to join via link, etc. Returns True on success. """ call = UnbanChatMember(chat_id=chat_id, user_id=user_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) async def restrict_chat_member( self, @@ -1387,6 +1444,7 @@ class Bot(ContextInstanceMixin["Bot"]): user_id: int, permissions: ChatPermissions, until_date: Optional[Union[datetime.datetime, datetime.timedelta, int]] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to restrict a user in a supergroup. The bot must be an administrator in @@ -1402,12 +1460,13 @@ class Bot(ContextInstanceMixin["Bot"]): :param until_date: Date when restrictions will be lifted for the user, unix time. If user is restricted for more than 366 days or less than 30 seconds from the current time, they are considered to be restricted forever + :param request_timeout: Request timeout :return: Returns True on success. """ call = RestrictChatMember( chat_id=chat_id, user_id=user_id, permissions=permissions, until_date=until_date, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def promote_chat_member( self, @@ -1421,6 +1480,7 @@ class Bot(ContextInstanceMixin["Bot"]): can_restrict_members: Optional[bool] = None, can_pin_messages: Optional[bool] = None, can_promote_members: Optional[bool] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to promote or demote a user in a supergroup or a channel. The bot must be @@ -1449,6 +1509,7 @@ class Bot(ContextInstanceMixin["Bot"]): with a subset of their own privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that were appointed by him) + :param request_timeout: Request timeout :return: Returns True on success. """ call = PromoteChatMember( @@ -1463,10 +1524,14 @@ class Bot(ContextInstanceMixin["Bot"]): can_pin_messages=can_pin_messages, can_promote_members=can_promote_members, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def set_chat_administrator_custom_title( - self, chat_id: Union[int, str], user_id: int, custom_title: str, + self, + chat_id: Union[int, str], + user_id: int, + custom_title: str, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to set a custom title for an administrator in a supergroup promoted by the @@ -1479,15 +1544,19 @@ class Bot(ContextInstanceMixin["Bot"]): :param user_id: Unique identifier of the target user :param custom_title: New custom title for the administrator; 0-16 characters, emoji are not allowed + :param request_timeout: Request timeout :return: Returns True on success. """ call = SetChatAdministratorCustomTitle( chat_id=chat_id, user_id=user_id, custom_title=custom_title, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def set_chat_permissions( - self, chat_id: Union[int, str], permissions: ChatPermissions, + self, + chat_id: Union[int, str], + permissions: ChatPermissions, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to set default chat permissions for all members. The bot must be an @@ -1499,12 +1568,15 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) :param permissions: New default chat permissions + :param request_timeout: Request timeout :return: Returns True on success. """ call = SetChatPermissions(chat_id=chat_id, permissions=permissions,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def export_chat_invite_link(self, chat_id: Union[int, str],) -> str: + async def export_chat_invite_link( + self, chat_id: Union[int, str], request_timeout: Optional[int] = None, + ) -> str: """ Use this method to generate a new invite link for a chat; any previously generated link is revoked. The bot must be an administrator in the chat for this to work and must have the @@ -1519,12 +1591,15 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :param request_timeout: Request timeout :return: Returns the new invite link as String on success. """ call = ExportChatInviteLink(chat_id=chat_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def set_chat_photo(self, chat_id: Union[int, str], photo: InputFile,) -> bool: + async def set_chat_photo( + self, chat_id: Union[int, str], photo: InputFile, request_timeout: Optional[int] = None, + ) -> bool: """ Use this method to set a new profile photo for the chat. Photos can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have @@ -1535,12 +1610,15 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :param photo: New chat photo, uploaded using multipart/form-data + :param request_timeout: Request timeout :return: Returns True on success. """ call = SetChatPhoto(chat_id=chat_id, photo=photo,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def delete_chat_photo(self, chat_id: Union[int, str],) -> bool: + async def delete_chat_photo( + self, chat_id: Union[int, str], request_timeout: Optional[int] = None, + ) -> bool: """ Use this method to delete a chat photo. Photos can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin @@ -1550,12 +1628,15 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :param request_timeout: Request timeout :return: Returns True on success. """ call = DeleteChatPhoto(chat_id=chat_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def set_chat_title(self, chat_id: Union[int, str], title: str,) -> bool: + async def set_chat_title( + self, chat_id: Union[int, str], title: str, request_timeout: Optional[int] = None, + ) -> bool: """ Use this method to change the title of a chat. Titles can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the @@ -1566,13 +1647,17 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :param title: New chat title, 1-255 characters + :param request_timeout: Request timeout :return: Returns True on success. """ call = SetChatTitle(chat_id=chat_id, title=title,) - return await self(call) + return await self(call, request_timeout=request_timeout) async def set_chat_description( - self, chat_id: Union[int, str], description: Optional[str] = None, + self, + chat_id: Union[int, str], + description: Optional[str] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to change the description of a group, a supergroup or a channel. The bot @@ -1584,21 +1669,23 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :param description: New chat description, 0-255 characters + :param request_timeout: Request timeout :return: Returns True on success. """ call = SetChatDescription(chat_id=chat_id, description=description,) - return await self(call) + return await self(call, request_timeout=request_timeout) async def pin_chat_message( self, chat_id: Union[int, str], message_id: int, disable_notification: Optional[bool] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to pin a message in a group, a supergroup, or a channel. The bot must be - an administrator in the chat for this to work and must have the ‘can_pin_messages’ admin - right in the supergroup or ‘can_edit_messages’ admin right in the channel. Returns True on + an administrator in the chat for this to work and must have the 'can_pin_messages' admin + right in the supergroup or 'can_edit_messages' admin right in the channel. Returns True on success. Source: https://core.telegram.org/bots/api#pinchatmessage @@ -1609,30 +1696,36 @@ class Bot(ContextInstanceMixin["Bot"]): :param disable_notification: Pass True, if it is not necessary to send a notification to all chat members about the new pinned message. Notifications are always disabled in channels. + :param request_timeout: Request timeout :return: Returns True on success. """ call = PinChatMessage( chat_id=chat_id, message_id=message_id, disable_notification=disable_notification, ) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def unpin_chat_message(self, chat_id: Union[int, str],) -> bool: + async def unpin_chat_message( + self, chat_id: Union[int, str], request_timeout: Optional[int] = None, + ) -> bool: """ Use this method to unpin a message in a group, a supergroup, or a channel. The bot must be - an administrator in the chat for this to work and must have the ‘can_pin_messages’ admin - right in the supergroup or ‘can_edit_messages’ admin right in the channel. Returns True on + an administrator in the chat for this to work and must have the 'can_pin_messages' admin + right in the supergroup or 'can_edit_messages' admin right in the channel. Returns True on success. Source: https://core.telegram.org/bots/api#unpinchatmessage :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :param request_timeout: Request timeout :return: Returns True on success. """ call = UnpinChatMessage(chat_id=chat_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def leave_chat(self, chat_id: Union[int, str],) -> bool: + async def leave_chat( + self, chat_id: Union[int, str], request_timeout: Optional[int] = None, + ) -> bool: """ Use this method for your bot to leave a group, supergroup or channel. Returns True on success. @@ -1641,12 +1734,15 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) + :param request_timeout: Request timeout :return: Returns True on success. """ call = LeaveChat(chat_id=chat_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def get_chat(self, chat_id: Union[int, str],) -> Chat: + async def get_chat( + self, chat_id: Union[int, str], request_timeout: Optional[int] = None, + ) -> Chat: """ Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.). Returns a @@ -1656,12 +1752,15 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) + :param request_timeout: Request timeout :return: Returns a Chat object on success. """ call = GetChat(chat_id=chat_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def get_chat_administrators(self, chat_id: Union[int, str],) -> List[ChatMember]: + async def get_chat_administrators( + self, chat_id: Union[int, str], request_timeout: Optional[int] = None, + ) -> List[ChatMember]: """ Use this method to get a list of administrators in a chat. On success, returns an Array of ChatMember objects that contains information about all chat administrators except other @@ -1672,15 +1771,18 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) + :param request_timeout: Request timeout :return: On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots. If the chat is a group or a supergroup and no administrators were appointed, only the creator will be returned. """ call = GetChatAdministrators(chat_id=chat_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def get_chat_members_count(self, chat_id: Union[int, str],) -> int: + async def get_chat_members_count( + self, chat_id: Union[int, str], request_timeout: Optional[int] = None, + ) -> int: """ Use this method to get the number of members in a chat. Returns Int on success. @@ -1688,12 +1790,15 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) + :param request_timeout: Request timeout :return: Returns Int on success. """ call = GetChatMembersCount(chat_id=chat_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def get_chat_member(self, chat_id: Union[int, str], user_id: int,) -> ChatMember: + async def get_chat_member( + self, chat_id: Union[int, str], user_id: int, request_timeout: Optional[int] = None, + ) -> ChatMember: """ Use this method to get information about a member of a chat. Returns a ChatMember object on success. @@ -1703,12 +1808,18 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) :param user_id: Unique identifier of the target user + :param request_timeout: Request timeout :return: Returns a ChatMember object on success. """ call = GetChatMember(chat_id=chat_id, user_id=user_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def set_chat_sticker_set(self, chat_id: Union[int, str], sticker_set_name: str,) -> bool: + async def set_chat_sticker_set( + self, + chat_id: Union[int, str], + sticker_set_name: str, + request_timeout: Optional[int] = None, + ) -> bool: """ Use this method to set a new group sticker set for a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Use @@ -1720,13 +1831,16 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) :param sticker_set_name: Name of the sticker set to be set as the group sticker set + :param request_timeout: Request timeout :return: Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success. """ call = SetChatStickerSet(chat_id=chat_id, sticker_set_name=sticker_set_name,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def delete_chat_sticker_set(self, chat_id: Union[int, str],) -> bool: + async def delete_chat_sticker_set( + self, chat_id: Union[int, str], request_timeout: Optional[int] = None, + ) -> bool: """ Use this method to delete a group sticker set from a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Use @@ -1737,11 +1851,12 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) + :param request_timeout: Request timeout :return: Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success. """ call = DeleteChatStickerSet(chat_id=chat_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) async def answer_callback_query( self, @@ -1750,6 +1865,7 @@ class Bot(ContextInstanceMixin["Bot"]): show_alert: Optional[bool] = None, url: Optional[str] = None, cache_time: Optional[int] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to send answers to callback queries sent from inline keyboards. The answer @@ -1773,6 +1889,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param cache_time: The maximum amount of time in seconds that the result of the callback query may be cached client-side. Telegram apps will support caching starting in version 3.14. Defaults to 0. + :param request_timeout: Request timeout :return: On success, True is returned. """ call = AnswerCallbackQuery( @@ -1782,9 +1899,11 @@ class Bot(ContextInstanceMixin["Bot"]): url=url, cache_time=cache_time, ) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def set_my_commands(self, commands: List[BotCommand],) -> bool: + async def set_my_commands( + self, commands: List[BotCommand], request_timeout: Optional[int] = None, + ) -> bool: """ Use this method to change the list of the bot's commands. Returns True on success. @@ -1792,22 +1911,24 @@ class Bot(ContextInstanceMixin["Bot"]): :param commands: A JSON-serialized list of bot commands to be set as the list of the bot's commands. At most 100 commands can be specified. + :param request_timeout: Request timeout :return: Returns True on success. """ call = SetMyCommands(commands=commands,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def get_my_commands(self,) -> List[BotCommand]: + async def get_my_commands(self, request_timeout: Optional[int] = None,) -> List[BotCommand]: """ Use this method to get the current list of the bot's commands. Requires no parameters. Returns Array of BotCommand on success. Source: https://core.telegram.org/bots/api#getmycommands + :param request_timeout: Request timeout :return: Returns Array of BotCommand on success. """ call = GetMyCommands() - return await self(call) + return await self(call, request_timeout=request_timeout) # ============================================================================================= # Group: Updating messages @@ -1823,6 +1944,7 @@ class Bot(ContextInstanceMixin["Bot"]): parse_mode: Optional[str] = UNSET, disable_web_page_preview: Optional[bool] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + request_timeout: Optional[int] = None, ) -> Union[Message, bool]: """ Use this method to edit text and game messages. On success, if edited message is sent by @@ -1842,6 +1964,7 @@ class Bot(ContextInstanceMixin["Bot"]): for more details. :param disable_web_page_preview: Disables link previews for links in this message :param reply_markup: A JSON-serialized object for an inline keyboard. + :param request_timeout: Request timeout :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. """ @@ -1854,7 +1977,7 @@ class Bot(ContextInstanceMixin["Bot"]): disable_web_page_preview=disable_web_page_preview, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def edit_message_caption( self, @@ -1864,6 +1987,7 @@ class Bot(ContextInstanceMixin["Bot"]): caption: Optional[str] = None, parse_mode: Optional[str] = UNSET, reply_markup: Optional[InlineKeyboardMarkup] = None, + request_timeout: Optional[int] = None, ) -> Union[Message, bool]: """ Use this method to edit captions of messages. On success, if edited message is sent by the @@ -1882,6 +2006,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param parse_mode: Mode for parsing entities in the message caption. See formatting options for more details. :param reply_markup: A JSON-serialized object for an inline keyboard. + :param request_timeout: Request timeout :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. """ @@ -1893,7 +2018,7 @@ class Bot(ContextInstanceMixin["Bot"]): parse_mode=parse_mode, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def edit_message_media( self, @@ -1902,6 +2027,7 @@ class Bot(ContextInstanceMixin["Bot"]): message_id: Optional[int] = None, inline_message_id: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + request_timeout: Optional[int] = None, ) -> Union[Message, bool]: """ Use this method to edit animation, audio, document, photo, or video messages. If a message @@ -1922,6 +2048,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param inline_message_id: Required if chat_id and message_id are not specified. Identifier of the inline message :param reply_markup: A JSON-serialized object for a new inline keyboard. + :param request_timeout: Request timeout :return: On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned. """ @@ -1932,7 +2059,7 @@ class Bot(ContextInstanceMixin["Bot"]): inline_message_id=inline_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def edit_message_reply_markup( self, @@ -1940,6 +2067,7 @@ class Bot(ContextInstanceMixin["Bot"]): message_id: Optional[int] = None, inline_message_id: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + request_timeout: Optional[int] = None, ) -> Union[Message, bool]: """ Use this method to edit only the reply markup of messages. On success, if edited message @@ -1955,6 +2083,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param inline_message_id: Required if chat_id and message_id are not specified. Identifier of the inline message :param reply_markup: A JSON-serialized object for an inline keyboard. + :param request_timeout: Request timeout :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. """ @@ -1964,13 +2093,14 @@ class Bot(ContextInstanceMixin["Bot"]): inline_message_id=inline_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def stop_poll( self, chat_id: Union[int, str], message_id: int, reply_markup: Optional[InlineKeyboardMarkup] = None, + request_timeout: Optional[int] = None, ) -> Poll: """ Use this method to stop a poll which was sent by the bot. On success, the stopped Poll @@ -1982,12 +2112,15 @@ class Bot(ContextInstanceMixin["Bot"]): (in the format @channelusername) :param message_id: Identifier of the original message with the poll :param reply_markup: A JSON-serialized object for a new message inline keyboard. + :param request_timeout: Request timeout :return: On success, the stopped Poll with the final results is returned. """ call = StopPoll(chat_id=chat_id, message_id=message_id, reply_markup=reply_markup,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def delete_message(self, chat_id: Union[int, str], message_id: int,) -> bool: + async def delete_message( + self, chat_id: Union[int, str], message_id: int, request_timeout: Optional[int] = None, + ) -> bool: """ Use this method to delete a message, including service messages, with the following limitations: @@ -2007,10 +2140,11 @@ class Bot(ContextInstanceMixin["Bot"]): :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :param message_id: Identifier of the message to delete + :param request_timeout: Request timeout :return: Returns True on success. """ call = DeleteMessage(chat_id=chat_id, message_id=message_id,) - return await self(call) + return await self(call, request_timeout=request_timeout) # ============================================================================================= # Group: Stickers @@ -2026,6 +2160,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] ] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send static .WEBP or animated .TGS stickers. On success, the sent @@ -2045,6 +2180,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendSticker( @@ -2054,21 +2190,26 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def get_sticker_set(self, name: str,) -> StickerSet: + async def get_sticker_set( + self, name: str, request_timeout: Optional[int] = None, + ) -> StickerSet: """ Use this method to get a sticker set. On success, a StickerSet object is returned. Source: https://core.telegram.org/bots/api#getstickerset :param name: Name of the sticker set + :param request_timeout: Request timeout :return: On success, a StickerSet object is returned. """ call = GetStickerSet(name=name,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def upload_sticker_file(self, user_id: int, png_sticker: InputFile,) -> File: + async def upload_sticker_file( + self, user_id: int, png_sticker: InputFile, request_timeout: Optional[int] = None, + ) -> File: """ Use this method to upload a .PNG file with a sticker for later use in createNewStickerSet and addStickerToSet methods (can be used multiple times). Returns the uploaded File on @@ -2080,10 +2221,11 @@ class Bot(ContextInstanceMixin["Bot"]): :param png_sticker: PNG image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. + :param request_timeout: Request timeout :return: Returns the uploaded File on success. """ call = UploadStickerFile(user_id=user_id, png_sticker=png_sticker,) - return await self(call) + return await self(call, request_timeout=request_timeout) async def create_new_sticker_set( self, @@ -2095,6 +2237,7 @@ class Bot(ContextInstanceMixin["Bot"]): tgs_sticker: Optional[InputFile] = None, contains_masks: Optional[bool] = None, mask_position: Optional[MaskPosition] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to create a new sticker set owned by a user. The bot will be able to edit @@ -2122,6 +2265,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param contains_masks: Pass True, if a set of mask stickers should be created :param mask_position: A JSON-serialized object for position where the mask should be placed on faces + :param request_timeout: Request timeout :return: Returns True on success. """ call = CreateNewStickerSet( @@ -2134,7 +2278,7 @@ class Bot(ContextInstanceMixin["Bot"]): contains_masks=contains_masks, mask_position=mask_position, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def add_sticker_to_set( self, @@ -2144,6 +2288,7 @@ class Bot(ContextInstanceMixin["Bot"]): png_sticker: Optional[Union[InputFile, str]] = None, tgs_sticker: Optional[InputFile] = None, mask_position: Optional[MaskPosition] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to add a new sticker to a set created by the bot. You must use exactly one @@ -2167,6 +2312,7 @@ class Bot(ContextInstanceMixin["Bot"]): for technical requirements :param mask_position: A JSON-serialized object for position where the mask should be placed on faces + :param request_timeout: Request timeout :return: Returns True on success. """ call = AddStickerToSet( @@ -2177,9 +2323,11 @@ class Bot(ContextInstanceMixin["Bot"]): tgs_sticker=tgs_sticker, mask_position=mask_position, ) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def set_sticker_position_in_set(self, sticker: str, position: int,) -> bool: + async def set_sticker_position_in_set( + self, sticker: str, position: int, request_timeout: Optional[int] = None, + ) -> bool: """ Use this method to move a sticker in a set created by the bot to a specific position. Returns True on success. @@ -2188,12 +2336,15 @@ class Bot(ContextInstanceMixin["Bot"]): :param sticker: File identifier of the sticker :param position: New sticker position in the set, zero-based + :param request_timeout: Request timeout :return: Returns True on success. """ call = SetStickerPositionInSet(sticker=sticker, position=position,) - return await self(call) + return await self(call, request_timeout=request_timeout) - async def delete_sticker_from_set(self, sticker: str,) -> bool: + async def delete_sticker_from_set( + self, sticker: str, request_timeout: Optional[int] = None, + ) -> bool: """ Use this method to delete a sticker from a set created by the bot. Returns True on success. @@ -2201,13 +2352,18 @@ class Bot(ContextInstanceMixin["Bot"]): Source: https://core.telegram.org/bots/api#deletestickerfromset :param sticker: File identifier of the sticker + :param request_timeout: Request timeout :return: Returns True on success. """ call = DeleteStickerFromSet(sticker=sticker,) - return await self(call) + return await self(call, request_timeout=request_timeout) async def set_sticker_set_thumb( - self, name: str, user_id: int, thumb: Optional[Union[InputFile, str]] = None, + self, + name: str, + user_id: int, + thumb: Optional[Union[InputFile, str]] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for @@ -2226,10 +2382,11 @@ class Bot(ContextInstanceMixin["Bot"]): String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data.. Animated sticker set thumbnail can't be uploaded via HTTP URL. + :param request_timeout: Request timeout :return: Returns True on success. """ call = SetStickerSetThumb(name=name, user_id=user_id, thumb=thumb,) - return await self(call) + return await self(call, request_timeout=request_timeout) # ============================================================================================= # Group: Inline mode @@ -2245,6 +2402,7 @@ class Bot(ContextInstanceMixin["Bot"]): next_offset: Optional[str] = None, switch_pm_text: Optional[str] = None, switch_pm_parameter: Optional[str] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Use this method to send answers to an inline query. On success, True is returned. @@ -2261,14 +2419,15 @@ class Bot(ContextInstanceMixin["Bot"]): user who sends the same query :param next_offset: Pass the offset that a client should send in the next query with the same text to receive more results. Pass an empty string if there are - no more results or if you don‘t support pagination. Offset length - can’t exceed 64 bytes. + no more results or if you don't support pagination. Offset length + can't exceed 64 bytes. :param switch_pm_text: If passed, clients will display a button with specified text that switches the user to a private chat with the bot and sends the bot a start message with the parameter switch_pm_parameter :param switch_pm_parameter: Deep-linking parameter for the /start message sent to the bot when user presses the switch button. 1-64 characters, only A-Z, a-z, 0-9, _ and - are allowed. + :param request_timeout: Request timeout :return: On success, True is returned. """ call = AnswerInlineQuery( @@ -2280,7 +2439,7 @@ class Bot(ContextInstanceMixin["Bot"]): switch_pm_text=switch_pm_text, switch_pm_parameter=switch_pm_parameter, ) - return await self(call) + return await self(call, request_timeout=request_timeout) # ============================================================================================= # Group: Payments @@ -2312,6 +2471,7 @@ class Bot(ContextInstanceMixin["Bot"]): disable_notification: Optional[bool] = None, reply_to_message_id: Optional[int] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send invoices. On success, the sent Message is returned. @@ -2356,6 +2516,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param reply_markup: A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendInvoice( @@ -2383,7 +2544,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def answer_shipping_query( self, @@ -2391,6 +2552,7 @@ class Bot(ContextInstanceMixin["Bot"]): ok: bool, shipping_options: Optional[List[ShippingOption]] = None, error_message: Optional[str] = None, + request_timeout: Optional[int] = None, ) -> bool: """ If you sent an invoice requesting a shipping address and the parameter is_flexible was @@ -2409,6 +2571,7 @@ class Bot(ContextInstanceMixin["Bot"]): explains why it is impossible to complete the order (e.g. "Sorry, delivery to your desired address is unavailable'). Telegram will display this message to the user. + :param request_timeout: Request timeout :return: On success, True is returned. """ call = AnswerShippingQuery( @@ -2417,10 +2580,14 @@ class Bot(ContextInstanceMixin["Bot"]): shipping_options=shipping_options, error_message=error_message, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def answer_pre_checkout_query( - self, pre_checkout_query_id: str, ok: bool, error_message: Optional[str] = None, + self, + pre_checkout_query_id: str, + ok: bool, + error_message: Optional[str] = None, + request_timeout: Optional[int] = None, ) -> bool: """ Once the user has confirmed their payment and shipping details, the Bot API sends the @@ -2439,12 +2606,13 @@ class Bot(ContextInstanceMixin["Bot"]): while you were busy filling out your payment details. Please choose a different color or garment!"). Telegram will display this message to the user. + :param request_timeout: Request timeout :return: On success, True is returned. """ call = AnswerPreCheckoutQuery( pre_checkout_query_id=pre_checkout_query_id, ok=ok, error_message=error_message, ) - return await self(call) + return await self(call, request_timeout=request_timeout) # ============================================================================================= # Group: Telegram Passport @@ -2452,7 +2620,10 @@ class Bot(ContextInstanceMixin["Bot"]): # ============================================================================================= async def set_passport_data_errors( - self, user_id: int, errors: List[PassportElementError], + self, + user_id: int, + errors: List[PassportElementError], + request_timeout: Optional[int] = None, ) -> bool: """ Informs a user that some of the Telegram Passport elements they provided contains errors. @@ -2468,12 +2639,13 @@ class Bot(ContextInstanceMixin["Bot"]): :param user_id: User identifier :param errors: A JSON-serialized array describing the errors + :param request_timeout: Request timeout :return: The user will not be able to re-submit their Passport to you until the errors are fixed (the contents of the field for which you returned the error must change). Returns True on success. """ call = SetPassportDataErrors(user_id=user_id, errors=errors,) - return await self(call) + return await self(call, request_timeout=request_timeout) # ============================================================================================= # Group: Games @@ -2487,6 +2659,7 @@ class Bot(ContextInstanceMixin["Bot"]): disable_notification: Optional[bool] = None, reply_to_message_id: Optional[int] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + request_timeout: Optional[int] = None, ) -> Message: """ Use this method to send a game. On success, the sent Message is returned. @@ -2499,9 +2672,10 @@ class Bot(ContextInstanceMixin["Bot"]): :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :param reply_to_message_id: If the message is a reply, ID of the original message - :param reply_markup: A JSON-serialized object for an inline keyboard. If empty, one ‘Play - game_title’ button will be shown. If not empty, the first button must + :param reply_markup: A JSON-serialized object for an inline keyboard. If empty, one 'Play + game_title' button will be shown. If not empty, the first button must launch the game. + :param request_timeout: Request timeout :return: On success, the sent Message is returned. """ call = SendGame( @@ -2511,7 +2685,7 @@ class Bot(ContextInstanceMixin["Bot"]): reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def set_game_score( self, @@ -2522,6 +2696,7 @@ class Bot(ContextInstanceMixin["Bot"]): chat_id: Optional[int] = None, message_id: Optional[int] = None, inline_message_id: Optional[str] = None, + request_timeout: Optional[int] = None, ) -> Union[Message, bool]: """ Use this method to set the score of the specified user in a game. On success, if the @@ -2543,6 +2718,7 @@ class Bot(ContextInstanceMixin["Bot"]): message :param inline_message_id: Required if chat_id and message_id are not specified. Identifier of the inline message + :param request_timeout: Request timeout :return: On success, if the message was sent by the bot, returns the edited Message, otherwise returns True. Returns an error, if the new score is not greater than the user's current score in the chat and force is False. @@ -2556,7 +2732,7 @@ class Bot(ContextInstanceMixin["Bot"]): message_id=message_id, inline_message_id=inline_message_id, ) - return await self(call) + return await self(call, request_timeout=request_timeout) async def get_game_high_scores( self, @@ -2564,6 +2740,7 @@ class Bot(ContextInstanceMixin["Bot"]): chat_id: Optional[int] = None, message_id: Optional[int] = None, inline_message_id: Optional[str] = None, + request_timeout: Optional[int] = None, ) -> List[GameHighScore]: """ Use this method to get data for high score tables. Will return the score of the specified @@ -2582,6 +2759,7 @@ class Bot(ContextInstanceMixin["Bot"]): message :param inline_message_id: Required if chat_id and message_id are not specified. Identifier of the inline message + :param request_timeout: Request timeout :return: Will return the score of the specified user and several of their neighbors in a game. On success, returns an Array of GameHighScore objects. This method will currently return scores for the target user, plus two of their closest neighbors @@ -2594,4 +2772,4 @@ class Bot(ContextInstanceMixin["Bot"]): message_id=message_id, inline_message_id=inline_message_id, ) - return await self(call) + return await self(call, request_timeout=request_timeout) diff --git a/aiogram/api/client/session/aiohttp.py b/aiogram/api/client/session/aiohttp.py index 774e7186..4ecfcea9 100644 --- a/aiogram/api/client/session/aiohttp.py +++ b/aiogram/api/client/session/aiohttp.py @@ -125,16 +125,16 @@ class AiohttpSession(BaseSession): form.add_field(key, value, filename=value.filename or key) return form - async def make_request(self, token: str, call: TelegramMethod[T]) -> T: + async def make_request( + self, token: str, call: TelegramMethod[T], timeout: Optional[int] = None + ) -> T: session = await self.create_session() request = call.build_request() url = self.api.api_url(token=token, method=request.method) form = self.build_form_data(request) - async with session.post( - url, data=form, timeout=call.request_timeout or self.timeout - ) as resp: + async with session.post(url, data=form, timeout=timeout or self.timeout) as resp: raw_result = await resp.json(loads=self.json_loads) response = call.build_response(raw_result) diff --git a/aiogram/api/client/session/base.py b/aiogram/api/client/session/base.py index 379e69ac..c49d4b5a 100644 --- a/aiogram/api/client/session/base.py +++ b/aiogram/api/client/session/base.py @@ -10,6 +10,7 @@ from aiogram.utils.exceptions import TelegramAPIError from ....utils.helper import Default from ...methods import Response, TelegramMethod +from ...types import UNSET from ..telegram import PRODUCTION, TelegramAPIServer T = TypeVar("T") @@ -18,9 +19,7 @@ _JsonDumps = Callable[..., str] class BaseSession(abc.ABC): - # global session timeout default_timeout: ClassVar[float] = 60.0 - api: Default[TelegramAPIServer] = Default(PRODUCTION) json_loads: Default[_JsonLoads] = Default(json.loads) json_dumps: Default[_JsonDumps] = Default(json.dumps) @@ -37,7 +36,9 @@ class BaseSession(abc.ABC): pass @abc.abstractmethod - async def make_request(self, token: str, method: TelegramMethod[T]) -> T: # pragma: no cover + async def make_request( + self, token: str, method: TelegramMethod[T], timeout: Optional[int] = UNSET + ) -> T: # pragma: no cover pass @abc.abstractmethod diff --git a/aiogram/api/methods/answer_inline_query.py b/aiogram/api/methods/answer_inline_query.py index a5b8bd7b..eb8a7138 100644 --- a/aiogram/api/methods/answer_inline_query.py +++ b/aiogram/api/methods/answer_inline_query.py @@ -26,8 +26,8 @@ class AnswerInlineQuery(TelegramMethod[bool]): query. By default, results may be returned to any user who sends the same query""" next_offset: Optional[str] = None """Pass the offset that a client should send in the next query with the same text to receive - more results. Pass an empty string if there are no more results or if you don‘t support - pagination. Offset length can’t exceed 64 bytes.""" + more results. Pass an empty string if there are no more results or if you don't support + pagination. Offset length can't exceed 64 bytes.""" switch_pm_text: Optional[str] = None """If passed, clients will display a button with specified text that switches the user to a private chat with the bot and sends the bot a start message with the parameter diff --git a/aiogram/api/methods/base.py b/aiogram/api/methods/base.py index 4fcd9ae9..40f251c0 100644 --- a/aiogram/api/methods/base.py +++ b/aiogram/api/methods/base.py @@ -69,13 +69,9 @@ class TelegramMethod(abc.ABC, BaseModel, Generic[T]): def build_request(self) -> Request: # pragma: no cover pass - request_timeout: Optional[float] = None - def dict(self, **kwargs: Any) -> Any: # override dict of pydantic.BaseModel to overcome exporting request_timeout field exclude = kwargs.pop("exclude", set()) - if isinstance(exclude, set): - exclude.add("request_timeout") return super().dict(exclude=exclude, **kwargs) diff --git a/aiogram/api/methods/edit_message_caption.py b/aiogram/api/methods/edit_message_caption.py index ebbe9c7b..733c357d 100644 --- a/aiogram/api/methods/edit_message_caption.py +++ b/aiogram/api/methods/edit_message_caption.py @@ -24,8 +24,7 @@ class EditMessageCaption(TelegramMethod[Union[Message, bool]]): caption: Optional[str] = None """New caption of the message, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the message caption. See formatting options for more details.""" reply_markup: Optional[InlineKeyboardMarkup] = None """A JSON-serialized object for an inline keyboard.""" diff --git a/aiogram/api/methods/edit_message_text.py b/aiogram/api/methods/edit_message_text.py index 20098fdc..23255e98 100644 --- a/aiogram/api/methods/edit_message_text.py +++ b/aiogram/api/methods/edit_message_text.py @@ -24,8 +24,7 @@ class EditMessageText(TelegramMethod[Union[Message, bool]]): inline_message_id: Optional[str] = None """Required if chat_id and message_id are not specified. Identifier of the inline message""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in your bot's message.""" + """Mode for parsing entities in the message text. See formatting options for more details.""" disable_web_page_preview: Optional[bool] = None """Disables link previews for links in this message""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/methods/pin_chat_message.py b/aiogram/api/methods/pin_chat_message.py index 1d7383e7..3f8a442d 100644 --- a/aiogram/api/methods/pin_chat_message.py +++ b/aiogram/api/methods/pin_chat_message.py @@ -6,8 +6,8 @@ from .base import Request, TelegramMethod class PinChatMessage(TelegramMethod[bool]): """ Use this method to pin a message in a group, a supergroup, or a channel. The bot must be an - administrator in the chat for this to work and must have the ‘can_pin_messages’ admin right in - the supergroup or ‘can_edit_messages’ admin right in the channel. Returns True on success. + administrator in the chat for this to work and must have the 'can_pin_messages' admin right in + the supergroup or 'can_edit_messages' admin right in the channel. Returns True on success. Source: https://core.telegram.org/bots/api#pinchatmessage """ diff --git a/aiogram/api/methods/send_animation.py b/aiogram/api/methods/send_animation.py index aca62a40..955ed9e9 100644 --- a/aiogram/api/methods/send_animation.py +++ b/aiogram/api/methods/send_animation.py @@ -39,16 +39,16 @@ class SendAnimation(TelegramMethod[Message]): thumb: Optional[Union[InputFile, str]] = None """Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. - A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded - using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new + A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded + using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under .""" caption: Optional[str] = None """Animation caption (may also be used when resending animation by file_id), 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the animation caption. See formatting options for more + details.""" disable_notification: Optional[bool] = None """Sends the message silently. Users will receive a notification with no sound.""" reply_to_message_id: Optional[int] = None diff --git a/aiogram/api/methods/send_audio.py b/aiogram/api/methods/send_audio.py index be4870c4..ca39408f 100644 --- a/aiogram/api/methods/send_audio.py +++ b/aiogram/api/methods/send_audio.py @@ -35,8 +35,7 @@ class SendAudio(TelegramMethod[Message]): caption: Optional[str] = None """Audio caption, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the audio caption. See formatting options for more details.""" duration: Optional[int] = None """Duration of the audio in seconds""" performer: Optional[str] = None @@ -46,8 +45,8 @@ class SendAudio(TelegramMethod[Message]): thumb: Optional[Union[InputFile, str]] = None """Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. - A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded - using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new + A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded + using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under .""" disable_notification: Optional[bool] = None diff --git a/aiogram/api/methods/send_dice.py b/aiogram/api/methods/send_dice.py index f200850e..fb767799 100644 --- a/aiogram/api/methods/send_dice.py +++ b/aiogram/api/methods/send_dice.py @@ -12,9 +12,8 @@ from .base import Request, TelegramMethod class SendDice(TelegramMethod[Message]): """ - Use this method to send a dice, which will have a random value from 1 to 6. On success, the - sent Message is returned. (Yes, we're aware of the 'proper' singular of die. But it's awkward, - and we decided to help it change. One dice at a time!) + Use this method to send an animated emoji that will display a random value. On success, the + sent Message is returned. Source: https://core.telegram.org/bots/api#senddice """ @@ -25,8 +24,8 @@ class SendDice(TelegramMethod[Message]): """Unique identifier for the target chat or username of the target channel (in the format @channelusername)""" emoji: Optional[str] = None - """Emoji on which the dice throw animation is based. Currently, must be one of '' or ''. - Defauts to ''""" + """Emoji on which the dice throw animation is based. Currently, must be one of '', '', or ''. + Dice can have values 1-6 for '' and '', and values 1-5 for ''. Defaults to ''""" disable_notification: Optional[bool] = None """Sends the message silently. Users will receive a notification with no sound.""" reply_to_message_id: Optional[int] = None diff --git a/aiogram/api/methods/send_document.py b/aiogram/api/methods/send_document.py index c67588e4..b6868135 100644 --- a/aiogram/api/methods/send_document.py +++ b/aiogram/api/methods/send_document.py @@ -33,16 +33,15 @@ class SendDocument(TelegramMethod[Message]): thumb: Optional[Union[InputFile, str]] = None """Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. - A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded - using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new + A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded + using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under .""" caption: Optional[str] = None """Document caption (may also be used when resending documents by file_id), 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the document caption. See formatting options for more details.""" disable_notification: Optional[bool] = None """Sends the message silently. Users will receive a notification with no sound.""" reply_to_message_id: Optional[int] = None diff --git a/aiogram/api/methods/send_game.py b/aiogram/api/methods/send_game.py index 0e32c6eb..9d760555 100644 --- a/aiogram/api/methods/send_game.py +++ b/aiogram/api/methods/send_game.py @@ -23,7 +23,7 @@ class SendGame(TelegramMethod[Message]): reply_to_message_id: Optional[int] = None """If the message is a reply, ID of the original message""" reply_markup: Optional[InlineKeyboardMarkup] = None - """A JSON-serialized object for an inline keyboard. If empty, one ‘Play game_title’ button + """A JSON-serialized object for an inline keyboard. If empty, one 'Play game_title' button will be shown. If not empty, the first button must launch the game.""" def build_request(self) -> Request: diff --git a/aiogram/api/methods/send_message.py b/aiogram/api/methods/send_message.py index 54f0fe37..44cc0fd2 100644 --- a/aiogram/api/methods/send_message.py +++ b/aiogram/api/methods/send_message.py @@ -26,8 +26,7 @@ class SendMessage(TelegramMethod[Message]): text: str """Text of the message to be sent, 1-4096 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in your bot's message.""" + """Mode for parsing entities in the message text. See formatting options for more details.""" disable_web_page_preview: Optional[bool] = None """Disables link previews for links in this message""" disable_notification: Optional[bool] = None diff --git a/aiogram/api/methods/send_photo.py b/aiogram/api/methods/send_photo.py index 89a25864..ab37099d 100644 --- a/aiogram/api/methods/send_photo.py +++ b/aiogram/api/methods/send_photo.py @@ -32,8 +32,7 @@ class SendPhoto(TelegramMethod[Message]): """Photo caption (may also be used when resending photos by file_id), 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the photo caption. See formatting options for more details.""" disable_notification: Optional[bool] = None """Sends the message silently. Users will receive a notification with no sound.""" reply_to_message_id: Optional[int] = None diff --git a/aiogram/api/methods/send_video.py b/aiogram/api/methods/send_video.py index f2659348..8784d134 100644 --- a/aiogram/api/methods/send_video.py +++ b/aiogram/api/methods/send_video.py @@ -39,16 +39,15 @@ class SendVideo(TelegramMethod[Message]): thumb: Optional[Union[InputFile, str]] = None """Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. - A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded - using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new + A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded + using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under .""" caption: Optional[str] = None """Video caption (may also be used when resending videos by file_id), 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the video caption. See formatting options for more details.""" supports_streaming: Optional[bool] = None """Pass True, if the uploaded video is suitable for streaming""" disable_notification: Optional[bool] = None diff --git a/aiogram/api/methods/send_video_note.py b/aiogram/api/methods/send_video_note.py index 05f55696..bb41045a 100644 --- a/aiogram/api/methods/send_video_note.py +++ b/aiogram/api/methods/send_video_note.py @@ -35,8 +35,8 @@ class SendVideoNote(TelegramMethod[Message]): thumb: Optional[Union[InputFile, str]] = None """Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. - A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded - using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new + A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded + using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under .""" disable_notification: Optional[bool] = None diff --git a/aiogram/api/methods/send_voice.py b/aiogram/api/methods/send_voice.py index 1369ad1c..945c6314 100644 --- a/aiogram/api/methods/send_voice.py +++ b/aiogram/api/methods/send_voice.py @@ -35,8 +35,8 @@ class SendVoice(TelegramMethod[Message]): caption: Optional[str] = None """Voice message caption, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the voice message caption. See formatting options for more + details.""" duration: Optional[int] = None """Duration of the voice message in seconds""" disable_notification: Optional[bool] = None diff --git a/aiogram/api/methods/set_webhook.py b/aiogram/api/methods/set_webhook.py index 905385ad..7da2d287 100644 --- a/aiogram/api/methods/set_webhook.py +++ b/aiogram/api/methods/set_webhook.py @@ -12,7 +12,7 @@ class SetWebhook(TelegramMethod[bool]): after a reasonable amount of attempts. Returns True on success. If you'd like to make sure that the Webhook request comes from Telegram, we recommend using a secret path in the URL, e.g. https://www.example.com/. Since nobody else knows your - bot‘s token, you can be pretty sure it’s us. + bot's token, you can be pretty sure it's us. Notes 1. You will not be able to receive updates using getUpdates for as long as an outgoing webhook is set up. @@ -34,8 +34,8 @@ class SetWebhook(TelegramMethod[bool]): our self-signed guide for details.""" max_connections: Optional[int] = None """Maximum allowed number of simultaneous HTTPS connections to the webhook for update - delivery, 1-100. Defaults to 40. Use lower values to limit the load on your bot‘s server, - and higher values to increase your bot’s throughput.""" + delivery, 1-100. Defaults to 40. Use lower values to limit the load on your bot's server, + and higher values to increase your bot's throughput.""" allowed_updates: Optional[List[str]] = None """A JSON-serialized list of the update types you want your bot to receive. For example, specify ['message', 'edited_channel_post', 'callback_query'] to only receive updates of diff --git a/aiogram/api/methods/unpin_chat_message.py b/aiogram/api/methods/unpin_chat_message.py index 20cee142..c205884d 100644 --- a/aiogram/api/methods/unpin_chat_message.py +++ b/aiogram/api/methods/unpin_chat_message.py @@ -6,8 +6,8 @@ from .base import Request, TelegramMethod class UnpinChatMessage(TelegramMethod[bool]): """ Use this method to unpin a message in a group, a supergroup, or a channel. The bot must be an - administrator in the chat for this to work and must have the ‘can_pin_messages’ admin right in - the supergroup or ‘can_edit_messages’ admin right in the channel. Returns True on success. + administrator in the chat for this to work and must have the 'can_pin_messages' admin right in + the supergroup or 'can_edit_messages' admin right in the channel. Returns True on success. Source: https://core.telegram.org/bots/api#unpinchatmessage """ diff --git a/aiogram/api/types/base.py b/aiogram/api/types/base.py index 06618234..99db1a01 100644 --- a/aiogram/api/types/base.py +++ b/aiogram/api/types/base.py @@ -24,4 +24,3 @@ class MutableTelegramObject(TelegramObject): UNSET: Any = sentinel.UNSET # special sentinel object which used in sutuation when None might be a useful value -print(id(UNSET)) diff --git a/aiogram/api/types/chat_member.py b/aiogram/api/types/chat_member.py index 593a86fb..dca3029e 100644 --- a/aiogram/api/types/chat_member.py +++ b/aiogram/api/types/chat_member.py @@ -3,8 +3,8 @@ from __future__ import annotations import datetime from typing import TYPE_CHECKING, Optional, Union -from .base import TelegramObject from ...utils import helper +from .base import TelegramObject if TYPE_CHECKING: # pragma: no cover from .user import User @@ -80,6 +80,7 @@ class ChatMemberStatus(helper.Helper): """ Chat member status """ + mode = helper.HelperMode.lowercase CREATOR = helper.Item() # creator diff --git a/aiogram/api/types/dice.py b/aiogram/api/types/dice.py index a85d54ac..d9b1da10 100644 --- a/aiogram/api/types/dice.py +++ b/aiogram/api/types/dice.py @@ -5,9 +5,7 @@ from .base import TelegramObject class Dice(TelegramObject): """ - This object represents a dice with a random value from 1 to 6 for currently supported base - emoji. (Yes, we're aware of the 'proper' singular of die. But it's awkward, and we decided to - help it change. One dice at a time!) + This object represents an animated emoji that displays a random value. Source: https://core.telegram.org/bots/api#dice """ @@ -15,7 +13,7 @@ class Dice(TelegramObject): emoji: str """Emoji on which the dice throw animation is based""" value: int - """Value of the dice, 1-6 for currently supported base emoji""" + """Value of the dice, 1-6 for '' and '' base emoji, 1-5 for '' base emoji""" class DiceEmoji: diff --git a/aiogram/api/types/force_reply.py b/aiogram/api/types/force_reply.py index 8ef4a1bd..8cbc1653 100644 --- a/aiogram/api/types/force_reply.py +++ b/aiogram/api/types/force_reply.py @@ -8,7 +8,7 @@ from .base import MutableTelegramObject class ForceReply(MutableTelegramObject): """ Upon receiving a message with this object, Telegram clients will display a reply interface to - the user (act as if the user has selected the bot‘s message and tapped ’Reply'). This can be + the user (act as if the user has selected the bot's message and tapped 'Reply'). This can be extremely useful if you want to create user-friendly step-by-step interfaces without having to sacrifice privacy mode. Example: A poll bot for groups runs in privacy mode (only receives commands, replies to its @@ -16,19 +16,19 @@ class ForceReply(MutableTelegramObject): Explain the user how to send a command with parameters (e.g. /newpoll question answer1 answer2). May be appealing for hardcore users but lacks modern day polish. - Guide the user through a step-by-step process. ‘Please send me your question’, ‘Cool, now - let’s add the first answer option‘, ’Great. Keep adding answer options, then send /done when - you‘re ready’. - The last option is definitely more attractive. And if you use ForceReply in your bot‘s - questions, it will receive the user’s answers even if it only receives replies, commands and + Guide the user through a step-by-step process. 'Please send me your question', 'Cool, now + let's add the first answer option', 'Great. Keep adding answer options, then send /done when + you're ready'. + The last option is definitely more attractive. And if you use ForceReply in your bot's + questions, it will receive the user's answers even if it only receives replies, commands and mentions — without any extra work for the user. Source: https://core.telegram.org/bots/api#forcereply """ force_reply: bool - """Shows reply interface to the user, as if they manually selected the bot‘s message and - tapped ’Reply'""" + """Shows reply interface to the user, as if they manually selected the bot's message and + tapped 'Reply'""" selective: Optional[bool] = None """Use this parameter if you want to force reply from specific users only. Targets: 1) users that are @mentioned in the text of the Message object; 2) if the bot's message is a reply diff --git a/aiogram/api/types/game_high_score.py b/aiogram/api/types/game_high_score.py index af8a1f3a..7bc35de6 100644 --- a/aiogram/api/types/game_high_score.py +++ b/aiogram/api/types/game_high_score.py @@ -11,7 +11,7 @@ if TYPE_CHECKING: # pragma: no cover class GameHighScore(TelegramObject): """ This object represents one row of the high scores table for a game. - And that‘s about all we’ve got for now. + And that's about all we've got for now. If you've got any questions, please check out our Bot FAQ Source: https://core.telegram.org/bots/api#gamehighscore diff --git a/aiogram/api/types/inline_keyboard_button.py b/aiogram/api/types/inline_keyboard_button.py index deb1f3c2..33ade442 100644 --- a/aiogram/api/types/inline_keyboard_button.py +++ b/aiogram/api/types/inline_keyboard_button.py @@ -28,11 +28,11 @@ class InlineKeyboardButton(MutableTelegramObject): """Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes""" switch_inline_query: Optional[str] = None """If set, pressing the button will prompt the user to select one of their chats, open that - chat and insert the bot‘s username and the specified inline query in the input field. Can - be empty, in which case just the bot’s username will be inserted.""" + chat and insert the bot's username and the specified inline query in the input field. Can + be empty, in which case just the bot's username will be inserted.""" switch_inline_query_current_chat: Optional[str] = None - """If set, pressing the button will insert the bot‘s username and the specified inline query - in the current chat’s input field. Can be empty, in which case only the bot's username will + """If set, pressing the button will insert the bot's username and the specified inline query + in the current chat's input field. Can be empty, in which case only the bot's username will be inserted.""" callback_game: Optional[CallbackGame] = None """Description of the game that will be launched when the user presses the button.""" diff --git a/aiogram/api/types/inline_query_result_audio.py b/aiogram/api/types/inline_query_result_audio.py index 687de9f0..b236f26d 100644 --- a/aiogram/api/types/inline_query_result_audio.py +++ b/aiogram/api/types/inline_query_result_audio.py @@ -34,8 +34,7 @@ class InlineQueryResultAudio(InlineQueryResult): caption: Optional[str] = None """Caption, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the audio caption. See formatting options for more details.""" performer: Optional[str] = None """Performer""" audio_duration: Optional[int] = None diff --git a/aiogram/api/types/inline_query_result_cached_audio.py b/aiogram/api/types/inline_query_result_cached_audio.py index af508b2e..b26edfed 100644 --- a/aiogram/api/types/inline_query_result_cached_audio.py +++ b/aiogram/api/types/inline_query_result_cached_audio.py @@ -32,8 +32,7 @@ class InlineQueryResultCachedAudio(InlineQueryResult): caption: Optional[str] = None """Caption, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the audio caption. See formatting options for more details.""" reply_markup: Optional[InlineKeyboardMarkup] = None """Inline keyboard attached to the message""" input_message_content: Optional[InputMessageContent] = None diff --git a/aiogram/api/types/inline_query_result_cached_document.py b/aiogram/api/types/inline_query_result_cached_document.py index f9024291..74fa2ecf 100644 --- a/aiogram/api/types/inline_query_result_cached_document.py +++ b/aiogram/api/types/inline_query_result_cached_document.py @@ -36,8 +36,7 @@ class InlineQueryResultCachedDocument(InlineQueryResult): caption: Optional[str] = None """Caption of the document to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the document caption. See formatting options for more details.""" reply_markup: Optional[InlineKeyboardMarkup] = None """Inline keyboard attached to the message""" input_message_content: Optional[InputMessageContent] = None diff --git a/aiogram/api/types/inline_query_result_cached_gif.py b/aiogram/api/types/inline_query_result_cached_gif.py index 3408a404..cb66af96 100644 --- a/aiogram/api/types/inline_query_result_cached_gif.py +++ b/aiogram/api/types/inline_query_result_cached_gif.py @@ -32,8 +32,7 @@ class InlineQueryResultCachedGif(InlineQueryResult): caption: Optional[str] = None """Caption of the GIF file to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the caption. See formatting options for more details.""" reply_markup: Optional[InlineKeyboardMarkup] = None """Inline keyboard attached to the message""" input_message_content: Optional[InputMessageContent] = None diff --git a/aiogram/api/types/inline_query_result_cached_mpeg4_gif.py b/aiogram/api/types/inline_query_result_cached_mpeg4_gif.py index 71a4e926..a43de25f 100644 --- a/aiogram/api/types/inline_query_result_cached_mpeg4_gif.py +++ b/aiogram/api/types/inline_query_result_cached_mpeg4_gif.py @@ -33,8 +33,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult): caption: Optional[str] = None """Caption of the MPEG-4 file to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the caption. See formatting options for more details.""" reply_markup: Optional[InlineKeyboardMarkup] = None """Inline keyboard attached to the message""" input_message_content: Optional[InputMessageContent] = None diff --git a/aiogram/api/types/inline_query_result_cached_photo.py b/aiogram/api/types/inline_query_result_cached_photo.py index 1e7abd57..b3a9f8a1 100644 --- a/aiogram/api/types/inline_query_result_cached_photo.py +++ b/aiogram/api/types/inline_query_result_cached_photo.py @@ -34,8 +34,7 @@ class InlineQueryResultCachedPhoto(InlineQueryResult): caption: Optional[str] = None """Caption of the photo to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the photo caption. See formatting options for more details.""" reply_markup: Optional[InlineKeyboardMarkup] = None """Inline keyboard attached to the message""" input_message_content: Optional[InputMessageContent] = None diff --git a/aiogram/api/types/inline_query_result_cached_video.py b/aiogram/api/types/inline_query_result_cached_video.py index b6161679..ef561bb4 100644 --- a/aiogram/api/types/inline_query_result_cached_video.py +++ b/aiogram/api/types/inline_query_result_cached_video.py @@ -34,8 +34,7 @@ class InlineQueryResultCachedVideo(InlineQueryResult): caption: Optional[str] = None """Caption of the video to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the video caption. See formatting options for more details.""" reply_markup: Optional[InlineKeyboardMarkup] = None """Inline keyboard attached to the message""" input_message_content: Optional[InputMessageContent] = None diff --git a/aiogram/api/types/inline_query_result_cached_voice.py b/aiogram/api/types/inline_query_result_cached_voice.py index 12491b88..aec92d44 100644 --- a/aiogram/api/types/inline_query_result_cached_voice.py +++ b/aiogram/api/types/inline_query_result_cached_voice.py @@ -34,8 +34,8 @@ class InlineQueryResultCachedVoice(InlineQueryResult): caption: Optional[str] = None """Caption, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the voice message caption. See formatting options for more + details.""" reply_markup: Optional[InlineKeyboardMarkup] = None """Inline keyboard attached to the message""" input_message_content: Optional[InputMessageContent] = None diff --git a/aiogram/api/types/inline_query_result_document.py b/aiogram/api/types/inline_query_result_document.py index 0c66579c..01e389ff 100644 --- a/aiogram/api/types/inline_query_result_document.py +++ b/aiogram/api/types/inline_query_result_document.py @@ -37,8 +37,7 @@ class InlineQueryResultDocument(InlineQueryResult): caption: Optional[str] = None """Caption of the document to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the document caption. See formatting options for more details.""" description: Optional[str] = None """Short description of the result""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/inline_query_result_gif.py b/aiogram/api/types/inline_query_result_gif.py index 1285b96f..8812c43a 100644 --- a/aiogram/api/types/inline_query_result_gif.py +++ b/aiogram/api/types/inline_query_result_gif.py @@ -28,20 +28,22 @@ class InlineQueryResultGif(InlineQueryResult): gif_url: str """A valid URL for the GIF file. File size must not exceed 1MB""" thumb_url: str - """URL of the static thumbnail for the result (jpeg or gif)""" + """URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result""" gif_width: Optional[int] = None """Width of the GIF""" gif_height: Optional[int] = None """Height of the GIF""" gif_duration: Optional[int] = None """Duration of the GIF""" + thumb_mime_type: Optional[str] = None + """MIME type of the thumbnail, must be one of 'image/jpeg', 'image/gif', or 'video/mp4'. + Defaults to 'image/jpeg'""" title: Optional[str] = None """Title for the result""" caption: Optional[str] = None """Caption of the GIF file to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the caption. See formatting options for more details.""" reply_markup: Optional[InlineKeyboardMarkup] = None """Inline keyboard attached to the message""" input_message_content: Optional[InputMessageContent] = None diff --git a/aiogram/api/types/inline_query_result_mpeg4_gif.py b/aiogram/api/types/inline_query_result_mpeg4_gif.py index 4fa6a8e9..76f97e0a 100644 --- a/aiogram/api/types/inline_query_result_mpeg4_gif.py +++ b/aiogram/api/types/inline_query_result_mpeg4_gif.py @@ -29,20 +29,22 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult): mpeg4_url: str """A valid URL for the MP4 file. File size must not exceed 1MB""" thumb_url: str - """URL of the static thumbnail (jpeg or gif) for the result""" + """URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result""" mpeg4_width: Optional[int] = None """Video width""" mpeg4_height: Optional[int] = None """Video height""" mpeg4_duration: Optional[int] = None """Video duration""" + thumb_mime_type: Optional[str] = None + """MIME type of the thumbnail, must be one of 'image/jpeg', 'image/gif', or 'video/mp4'. + Defaults to 'image/jpeg'""" title: Optional[str] = None """Title for the result""" caption: Optional[str] = None """Caption of the MPEG-4 file to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the caption. See formatting options for more details.""" reply_markup: Optional[InlineKeyboardMarkup] = None """Inline keyboard attached to the message""" input_message_content: Optional[InputMessageContent] = None diff --git a/aiogram/api/types/inline_query_result_photo.py b/aiogram/api/types/inline_query_result_photo.py index 5927c62c..31cddee2 100644 --- a/aiogram/api/types/inline_query_result_photo.py +++ b/aiogram/api/types/inline_query_result_photo.py @@ -40,8 +40,7 @@ class InlineQueryResultPhoto(InlineQueryResult): caption: Optional[str] = None """Caption of the photo to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the photo caption. See formatting options for more details.""" reply_markup: Optional[InlineKeyboardMarkup] = None """Inline keyboard attached to the message""" input_message_content: Optional[InputMessageContent] = None diff --git a/aiogram/api/types/inline_query_result_video.py b/aiogram/api/types/inline_query_result_video.py index 5ea390ed..3002b8be 100644 --- a/aiogram/api/types/inline_query_result_video.py +++ b/aiogram/api/types/inline_query_result_video.py @@ -38,8 +38,7 @@ class InlineQueryResultVideo(InlineQueryResult): caption: Optional[str] = None """Caption of the video to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the video caption. See formatting options for more details.""" video_width: Optional[int] = None """Video width""" video_height: Optional[int] = None diff --git a/aiogram/api/types/inline_query_result_voice.py b/aiogram/api/types/inline_query_result_voice.py index 74d17448..724d46bc 100644 --- a/aiogram/api/types/inline_query_result_voice.py +++ b/aiogram/api/types/inline_query_result_voice.py @@ -35,8 +35,8 @@ class InlineQueryResultVoice(InlineQueryResult): caption: Optional[str] = None """Caption, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the voice message caption. See formatting options for more + details.""" voice_duration: Optional[int] = None """Recording duration in seconds""" reply_markup: Optional[InlineKeyboardMarkup] = None diff --git a/aiogram/api/types/input_media_animation.py b/aiogram/api/types/input_media_animation.py index e62dc95e..d30084a2 100644 --- a/aiogram/api/types/input_media_animation.py +++ b/aiogram/api/types/input_media_animation.py @@ -28,15 +28,15 @@ class InputMediaAnimation(InputMedia): thumb: Optional[Union[InputFile, str]] = None """Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. - A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded - using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new + A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded + using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under .""" caption: Optional[str] = None """Caption of the animation to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the animation caption. See formatting options for more + details.""" width: Optional[int] = None """Animation width""" height: Optional[int] = None diff --git a/aiogram/api/types/input_media_audio.py b/aiogram/api/types/input_media_audio.py index 40059bd9..098087d1 100644 --- a/aiogram/api/types/input_media_audio.py +++ b/aiogram/api/types/input_media_audio.py @@ -28,15 +28,14 @@ class InputMediaAudio(InputMedia): thumb: Optional[Union[InputFile, str]] = None """Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. - A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded - using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new + A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded + using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under .""" caption: Optional[str] = None """Caption of the audio to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the audio caption. See formatting options for more details.""" duration: Optional[int] = None """Duration of the audio in seconds""" performer: Optional[str] = None diff --git a/aiogram/api/types/input_media_document.py b/aiogram/api/types/input_media_document.py index d57f1178..e29a5014 100644 --- a/aiogram/api/types/input_media_document.py +++ b/aiogram/api/types/input_media_document.py @@ -28,12 +28,11 @@ class InputMediaDocument(InputMedia): thumb: Optional[Union[InputFile, str]] = None """Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. - A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded - using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new + A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded + using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under .""" caption: Optional[str] = None """Caption of the document to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the document caption. See formatting options for more details.""" diff --git a/aiogram/api/types/input_media_photo.py b/aiogram/api/types/input_media_photo.py index c92b45e4..6ef61006 100644 --- a/aiogram/api/types/input_media_photo.py +++ b/aiogram/api/types/input_media_photo.py @@ -28,5 +28,4 @@ class InputMediaPhoto(InputMedia): caption: Optional[str] = None """Caption of the photo to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the photo caption. See formatting options for more details.""" diff --git a/aiogram/api/types/input_media_video.py b/aiogram/api/types/input_media_video.py index 61e73c1e..d8dc0adf 100644 --- a/aiogram/api/types/input_media_video.py +++ b/aiogram/api/types/input_media_video.py @@ -28,15 +28,14 @@ class InputMediaVideo(InputMedia): thumb: Optional[Union[InputFile, str]] = None """Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. - A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded - using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new + A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded + using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using multipart/form-data under .""" caption: Optional[str] = None """Caption of the video to be sent, 0-1024 characters after entities parsing""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in the media caption.""" + """Mode for parsing entities in the video caption. See formatting options for more details.""" width: Optional[int] = None """Video width""" height: Optional[int] = None diff --git a/aiogram/api/types/input_text_message_content.py b/aiogram/api/types/input_text_message_content.py index 3c5bda13..389cb48e 100644 --- a/aiogram/api/types/input_text_message_content.py +++ b/aiogram/api/types/input_text_message_content.py @@ -16,7 +16,6 @@ class InputTextMessageContent(InputMessageContent): message_text: str """Text of the message to be sent, 1-4096 characters""" parse_mode: Optional[str] = UNSET - """Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or - inline URLs in your bot's message.""" + """Mode for parsing entities in the message text. See formatting options for more details.""" disable_web_page_preview: Optional[bool] = None """Disables link previews for links in the sent message""" diff --git a/aiogram/api/types/message.py b/aiogram/api/types/message.py index 68b56209..589de26e 100644 --- a/aiogram/api/types/message.py +++ b/aiogram/api/types/message.py @@ -90,6 +90,8 @@ class Message(TelegramObject): reply_to_message: Optional[Message] = None """For replies, the original message. Note that the Message object in this field will not contain further reply_to_message fields even if it itself is a reply.""" + via_bot: Optional[User] = None + """Bot through which the message was sent""" edit_date: Optional[int] = None """Date the message was last edited in Unix time""" media_group_id: Optional[str] = None @@ -101,40 +103,41 @@ class Message(TelegramObject): entities: Optional[List[MessageEntity]] = None """For text messages, special entities like usernames, URLs, bot commands, etc. that appear in the text""" - caption_entities: Optional[List[MessageEntity]] = None - """For messages with a caption, special entities like usernames, URLs, bot commands, etc. that - appear in the caption""" + animation: Optional[Animation] = None + """Message is an animation, information about the animation. For backward compatibility, when + this field is set, the document field will also be set""" audio: Optional[Audio] = None """Message is an audio file, information about the file""" document: Optional[Document] = None """Message is a general file, information about the file""" - animation: Optional[Animation] = None - """Message is an animation, information about the animation. For backward compatibility, when - this field is set, the document field will also be set""" - game: Optional[Game] = None - """Message is a game, information about the game.""" photo: Optional[List[PhotoSize]] = None """Message is a photo, available sizes of the photo""" sticker: Optional[Sticker] = None """Message is a sticker, information about the sticker""" video: Optional[Video] = None """Message is a video, information about the video""" - voice: Optional[Voice] = None - """Message is a voice message, information about the file""" video_note: Optional[VideoNote] = None """Message is a video note, information about the video message""" + voice: Optional[Voice] = None + """Message is a voice message, information about the file""" caption: Optional[str] = None """Caption for the animation, audio, document, photo, video or voice, 0-1024 characters""" + caption_entities: Optional[List[MessageEntity]] = None + """For messages with a caption, special entities like usernames, URLs, bot commands, etc. that + appear in the caption""" contact: Optional[Contact] = None """Message is a shared contact, information about the contact""" - location: Optional[Location] = None - """Message is a shared location, information about the location""" - venue: Optional[Venue] = None - """Message is a venue, information about the venue""" - poll: Optional[Poll] = None - """Message is a native poll, information about the poll""" dice: Optional[Dice] = None """Message is a dice with random value from 1 to 6""" + game: Optional[Game] = None + """Message is a game, information about the game.""" + poll: Optional[Poll] = None + """Message is a native poll, information about the poll""" + venue: Optional[Venue] = None + """Message is a venue, information about the venue. For backward compatibility, when this + field is set, the location field will also be set""" + location: Optional[Location] = None + """Message is a shared location, information about the location""" new_chat_members: Optional[List[User]] = None """New members that were added to the group or supergroup and information about them (the bot itself may be one of these members)""" @@ -150,13 +153,13 @@ class Message(TelegramObject): group_chat_created: Optional[bool] = None """Service message: the group has been created""" supergroup_chat_created: Optional[bool] = None - """Service message: the supergroup has been created. This field can‘t be received in a message - coming through updates, because bot can’t be a member of a supergroup when it is created. + """Service message: the supergroup has been created. This field can't be received in a message + coming through updates, because bot can't be a member of a supergroup when it is created. It can only be found in reply_to_message if someone replies to a very first message in a directly created supergroup.""" channel_chat_created: Optional[bool] = None - """Service message: the channel has been created. This field can‘t be received in a message - coming through updates, because bot can’t be a member of a channel when it is created. It + """Service message: the channel has been created. This field can't be received in a message + coming through updates, because bot can't be a member of a channel when it is created. It can only be found in reply_to_message if someone replies to a very first message in a channel.""" migrate_to_chat_id: Optional[int] = None diff --git a/aiogram/api/types/update.py b/aiogram/api/types/update.py index fa89aa74..84803baa 100644 --- a/aiogram/api/types/update.py +++ b/aiogram/api/types/update.py @@ -24,8 +24,8 @@ class Update(TelegramObject): """ update_id: int - """The update‘s unique identifier. Update identifiers start from a certain positive number and - increase sequentially. This ID becomes especially handy if you’re using Webhooks, since it + """The update's unique identifier. Update identifiers start from a certain positive number and + increase sequentially. This ID becomes especially handy if you're using Webhooks, since it allows you to ignore repeated updates or to restore the correct update sequence, should they get out of order. If there are no new updates for at least a week, then identifier of the next update will be chosen randomly instead of sequentially.""" diff --git a/aiogram/api/types/user.py b/aiogram/api/types/user.py index e3a9eee1..15c87c12 100644 --- a/aiogram/api/types/user.py +++ b/aiogram/api/types/user.py @@ -17,11 +17,11 @@ class User(TelegramObject): is_bot: bool """True, if this user is a bot""" first_name: str - """User‘s or bot’s first name""" + """User's or bot's first name""" last_name: Optional[str] = None - """User‘s or bot’s last name""" + """User's or bot's last name""" username: Optional[str] = None - """User‘s or bot’s username""" + """User's or bot's username""" language_code: Optional[str] = None """IETF language tag of the user's language""" can_join_groups: Optional[bool] = None diff --git a/docs/_api_version.md b/docs/_api_version.md index ef216a53..86a9588a 100644 --- a/docs/_api_version.md +++ b/docs/_api_version.md @@ -1 +1 @@ -4.8 +4.9 diff --git a/docs/_package_version.md b/docs/_package_version.md index 255dd065..78e56ffb 100644 --- a/docs/_package_version.md +++ b/docs/_package_version.md @@ -1 +1 @@ -3.0.0a4 +3.0.0a5 diff --git a/poetry.lock b/poetry.lock index 72a5c042..d81c8b2f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -130,7 +130,7 @@ description = "Specifications for callback functions passed in to an API" name = "backcall" optional = false python-versions = "*" -version = "0.1.0" +version = "0.2.0" [[package]] category = "dev" @@ -191,7 +191,7 @@ description = "Python package for providing Mozilla's CA Bundle." name = "certifi" optional = false python-versions = "*" -version = "2020.4.5.1" +version = "2020.4.5.2" [[package]] category = "dev" @@ -322,7 +322,7 @@ description = "the modular source code checker: pep8 pyflakes and co" name = "flake8" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "3.8.2" +version = "3.8.3" [package.dependencies] mccabe = ">=0.6.0,<0.7.0" @@ -380,7 +380,7 @@ description = "File identification library for Python" name = "identify" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "1.4.16" +version = "1.4.19" [package.extras] license = ["editdistance"] @@ -414,14 +414,14 @@ description = "Read metadata from Python packages" name = "importlib-metadata" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -version = "1.6.0" +version = "1.6.1" [package.dependencies] zipp = ">=0.5" [package.extras] docs = ["sphinx", "rst.linker"] -testing = ["packaging", "importlib-resources"] +testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] [[package]] category = "dev" @@ -429,7 +429,7 @@ description = "IPython: Productive Interactive Computing" name = "ipython" optional = false python-versions = ">=3.6" -version = "7.14.0" +version = "7.15.0" [package.dependencies] appnope = "*" @@ -445,7 +445,7 @@ setuptools = ">=18.5" traitlets = ">=4.2" [package.extras] -all = ["nose (>=0.10.1)", "Sphinx (>=1.3)", "testpath", "nbformat", "ipywidgets", "qtconsole", "numpy (>=1.14)", "notebook", "ipyparallel", "ipykernel", "pygments", "requests", "nbconvert"] +all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.14)", "pygments", "qtconsole", "requests", "testpath"] doc = ["Sphinx (>=1.3)"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] @@ -576,11 +576,14 @@ description = "Python LiveReload is an awesome tool for web developers" name = "livereload" optional = false python-versions = "*" -version = "2.6.1" +version = "2.6.2" [package.dependencies] six = "*" -tornado = "*" + +[package.dependencies.tornado] +python = ">=2.8" +version = "*" [[package]] category = "dev" @@ -715,7 +718,7 @@ description = "More routines for operating on iterables, beyond itertools" name = "more-itertools" optional = false python-versions = ">=3.5" -version = "8.3.0" +version = "8.4.0" [[package]] category = "dev" @@ -786,7 +789,7 @@ description = "Node.js virtual environment builder" name = "nodeenv" optional = false python-versions = "*" -version = "1.3.5" +version = "1.4.0" [[package]] category = "dev" @@ -879,7 +882,7 @@ description = "Python dependency management and packaging made easy." name = "poetry" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.0.5" +version = "1.0.9" [package.dependencies] cachy = ">=0.3.0,<0.4.0" @@ -914,7 +917,7 @@ description = "A framework for managing and maintaining multi-language pre-commi name = "pre-commit" optional = false python-versions = ">=3.6.1" -version = "2.4.0" +version = "2.5.1" [package.dependencies] cfgv = ">=2.0.0" @@ -942,7 +945,6 @@ wcwidth = "*" [[package]] category = "dev" description = "Run a subprocess in a pseudo terminal" -marker = "sys_platform != \"win32\"" name = "ptyprocess" optional = false python-versions = "*" @@ -1046,7 +1048,7 @@ description = "pytest: simple powerful testing with Python" name = "pytest" optional = false python-versions = ">=3.5" -version = "5.4.2" +version = "5.4.3" [package.dependencies] atomicwrites = ">=1.0" @@ -1086,11 +1088,11 @@ description = "Pytest plugin for measuring coverage." name = "pytest-cov" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.9.0" +version = "2.10.0" [package.dependencies] coverage = ">=4.4" -pytest = ">=3.6" +pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests (2.0.2)", "six", "pytest-xdist", "virtualenv"] @@ -1184,7 +1186,7 @@ description = "Alternative regular expression module, to replace re." name = "regex" optional = false python-versions = "*" -version = "2020.5.14" +version = "2020.6.8" [[package]] category = "dev" @@ -1275,7 +1277,7 @@ marker = "python_version > \"2.7\"" name = "tqdm" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*" -version = "4.46.0" +version = "4.46.1" [package.extras] dev = ["py-make (>=0.1.0)", "twine", "argopt", "pydoc-markdown"] @@ -1340,7 +1342,7 @@ description = "Virtual Python Environment builder" name = "virtualenv" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "20.0.21" +version = "20.0.23" [package.dependencies] appdirs = ">=1.4.3,<2" @@ -1354,15 +1356,15 @@ version = ">=0.12,<2" [package.extras] docs = ["sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)", "proselint (>=0.10.2)"] -testing = ["pytest (>=4)", "coverage (>=5)", "coverage-enable-subprocess (>=1)", "pytest-xdist (>=1.31.0)", "pytest-mock (>=2)", "pytest-env (>=0.6.2)", "pytest-randomly (>=1)", "pytest-timeout", "packaging (>=20.0)", "xonsh (>=0.9.16)"] +testing = ["pytest (>=4)", "coverage (>=5)", "coverage-enable-subprocess (>=1)", "pytest-xdist (>=1.31.0)", "pytest-mock (>=2)", "pytest-env (>=0.6.2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "flaky (>=3)", "packaging (>=20.0)", "xonsh (>=0.9.16)"] [[package]] category = "dev" -description = "Measures number of Terminal column cells of wide-character codes" +description = "Measures the displayed width of unicode strings in a terminal" name = "wcwidth" optional = false python-versions = "*" -version = "0.1.9" +version = "0.2.4" [[package]] category = "dev" @@ -1463,8 +1465,8 @@ babel = [ {file = "Babel-2.8.0.tar.gz", hash = "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38"}, ] backcall = [ - {file = "backcall-0.1.0.tar.gz", hash = "sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4"}, - {file = "backcall-0.1.0.zip", hash = "sha256:bbbf4b1e5cd2bdb08f915895b51081c041bac22394fdfcfdfbe9f14b77c08bf2"}, + {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, + {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] black = [ {file = "black-19.10b0-py36-none-any.whl", hash = "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b"}, @@ -1479,8 +1481,8 @@ cachy = [ {file = "cachy-0.3.0.tar.gz", hash = "sha256:186581f4ceb42a0bbe040c407da73c14092379b1e4c0e327fdb72ae4a9b269b1"}, ] certifi = [ - {file = "certifi-2020.4.5.1-py2.py3-none-any.whl", hash = "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304"}, - {file = "certifi-2020.4.5.1.tar.gz", hash = "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"}, + {file = "certifi-2020.4.5.2-py2.py3-none-any.whl", hash = "sha256:9cd41137dc19af6a5e03b630eefe7d1f458d964d406342dd3edf625839b944cc"}, + {file = "certifi-2020.4.5.2.tar.gz", hash = "sha256:5ad7e9a056d25ffa5082862e36f119f7f7cec6457fa07ee2f8c339814b80c9b1"}, ] cffi = [ {file = "cffi-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384"}, @@ -1602,8 +1604,8 @@ filelock = [ {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"}, ] flake8 = [ - {file = "flake8-3.8.2-py2.py3-none-any.whl", hash = "sha256:ccaa799ef9893cebe69fdfefed76865aeaefbb94cb8545617b2298786a4de9a5"}, - {file = "flake8-3.8.2.tar.gz", hash = "sha256:c69ac1668e434d37a2d2880b3ca9aafd54b3a10a3ac1ab101d22f29e29cf8634"}, + {file = "flake8-3.8.3-py2.py3-none-any.whl", hash = "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c"}, + {file = "flake8-3.8.3.tar.gz", hash = "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208"}, ] flake8-html = [ {file = "flake8-html-0.4.1.tar.gz", hash = "sha256:2fb436cbfe1e109275bc8fb7fdd0cb00e67b3b48cfeb397309b6b2c61eeb4cb4"}, @@ -1617,8 +1619,8 @@ html5lib = [ {file = "html5lib-1.0.1.tar.gz", hash = "sha256:66cb0dcfdbbc4f9c3ba1a63fdb511ffdbd4f513b2b6d81b80cd26ce6b3fb3736"}, ] identify = [ - {file = "identify-1.4.16-py2.py3-none-any.whl", hash = "sha256:0f3c3aac62b51b86fea6ff52fe8ff9e06f57f10411502443809064d23e16f1c2"}, - {file = "identify-1.4.16.tar.gz", hash = "sha256:f9ad3d41f01e98eb066b6e05c5b184fd1e925fadec48eb165b4e01c72a1ef3a7"}, + {file = "identify-1.4.19-py2.py3-none-any.whl", hash = "sha256:781fd3401f5d2b17b22a8b18b493a48d5d948e3330634e82742e23f9c20234ef"}, + {file = "identify-1.4.19.tar.gz", hash = "sha256:249ebc7e2066d6393d27c1b1be3b70433f824a120b1d8274d362f1eb419e3b52"}, ] idna = [ {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, @@ -1627,12 +1629,12 @@ idna = [ importlib-metadata = [ {file = "importlib_metadata-1.1.3-py2.py3-none-any.whl", hash = "sha256:7c7f8ac40673f507f349bef2eed21a0e5f01ddf5b2a7356a6c65eb2099b53764"}, {file = "importlib_metadata-1.1.3.tar.gz", hash = "sha256:7a99fb4084ffe6dae374961ba7a6521b79c1d07c658ab3a28aa264ee1d1b14e3"}, - {file = "importlib_metadata-1.6.0-py2.py3-none-any.whl", hash = "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f"}, - {file = "importlib_metadata-1.6.0.tar.gz", hash = "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"}, + {file = "importlib_metadata-1.6.1-py2.py3-none-any.whl", hash = "sha256:15ec6c0fd909e893e3a08b3a7c76ecb149122fb14b7efe1199ddd4c7c57ea958"}, + {file = "importlib_metadata-1.6.1.tar.gz", hash = "sha256:0505dd08068cfec00f53a74a0ad927676d7757da81b7436a6eefe4c7cf75c545"}, ] ipython = [ - {file = "ipython-7.14.0-py3-none-any.whl", hash = "sha256:5b241b84bbf0eb085d43ae9d46adf38a13b45929ca7774a740990c2c242534bb"}, - {file = "ipython-7.14.0.tar.gz", hash = "sha256:f0126781d0f959da852fb3089e170ed807388e986a8dd4e6ac44855845b0fb1c"}, + {file = "ipython-7.15.0-py3-none-any.whl", hash = "sha256:1b85d65632211bf5d3e6f1406f3393c8c429a47d7b947b9a87812aa5bce6595c"}, + {file = "ipython-7.15.0.tar.gz", hash = "sha256:0ef1433879816a960cd3ae1ae1dc82c64732ca75cec8dab5a4e29783fb571d0e"}, ] ipython-genutils = [ {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, @@ -1667,8 +1669,7 @@ keyring = [ {file = "keyring-20.0.1.tar.gz", hash = "sha256:963bfa7f090269d30bdc5e25589e5fd9dad2cf2a7c6f176a7f2386910e5d0d8d"}, ] livereload = [ - {file = "livereload-2.6.1-py2.py3-none-any.whl", hash = "sha256:78d55f2c268a8823ba499305dcac64e28ddeb9a92571e12d543cd304faf5817b"}, - {file = "livereload-2.6.1.tar.gz", hash = "sha256:89254f78d7529d7ea0a3417d224c34287ebfe266b05e67e51facaf82c27f0f66"}, + {file = "livereload-2.6.2.tar.gz", hash = "sha256:d1eddcb5c5eb8d2ca1fa1f750e580da624c0f7fcb734aa5780dc81b7dcbd89be"}, ] lockfile = [ {file = "lockfile-0.12.2-py2.py3-none-any.whl", hash = "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"}, @@ -1760,8 +1761,8 @@ mkdocs-material = [ {file = "mkdocs_material-4.6.3-py2.py3-none-any.whl", hash = "sha256:7f3afa0a09c07d0b89a6a9755fdb00513aee8f0cec3538bb903325c80f66f444"}, ] more-itertools = [ - {file = "more-itertools-8.3.0.tar.gz", hash = "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be"}, - {file = "more_itertools-8.3.0-py3-none-any.whl", hash = "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982"}, + {file = "more-itertools-8.4.0.tar.gz", hash = "sha256:68c70cc7167bdf5c7c9d8f6954a7837089c6a36bf565383919bb595efb8a17e5"}, + {file = "more_itertools-8.4.0-py3-none-any.whl", hash = "sha256:b78134b2063dd214000685165d81c154522c3ee0a1c0d4d113c80361c234c5a2"}, ] msgpack = [ {file = "msgpack-1.0.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:cec8bf10981ed70998d98431cd814db0ecf3384e6b113366e7f36af71a0fca08"}, @@ -1826,7 +1827,7 @@ nltk = [ {file = "nltk-3.5.zip", hash = "sha256:845365449cd8c5f9731f7cb9f8bd6fd0767553b9d53af9eb1b3abf7700936b35"}, ] nodeenv = [ - {file = "nodeenv-1.3.5-py2.py3-none-any.whl", hash = "sha256:5b2438f2e42af54ca968dd1b374d14a1194848955187b0e5e4be1f73813a5212"}, + {file = "nodeenv-1.4.0-py2.py3-none-any.whl", hash = "sha256:4b0b77afa3ba9b54f4b6396e60b0c83f59eaeb2d63dc3cc7a70f7f4af96c82bc"}, ] packaging = [ {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, @@ -1861,12 +1862,12 @@ pluggy = [ {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] poetry = [ - {file = "poetry-1.0.5-py2.py3-none-any.whl", hash = "sha256:81cdb3c708fe03cdef484ccd6c3becc74811dce2b15cb67444c2495b1240a278"}, - {file = "poetry-1.0.5.tar.gz", hash = "sha256:8e195ea8a4bce4f418a23fd828aa2f9ce06be7655720efd1d95beb0ee641030a"}, + {file = "poetry-1.0.9-py2.py3-none-any.whl", hash = "sha256:27e0c9c16f785156a8d8d0e98a73e239c8d2083306c180718825d11d5664aea0"}, + {file = "poetry-1.0.9.tar.gz", hash = "sha256:0a4c56983546964b47cbbe0e1b49fef5662277bbf0673e3e350e1215560377ab"}, ] pre-commit = [ - {file = "pre_commit-2.4.0-py2.py3-none-any.whl", hash = "sha256:5559e09afcac7808933951ffaf4ff9aac524f31efbc3f24d021540b6c579813c"}, - {file = "pre_commit-2.4.0.tar.gz", hash = "sha256:703e2e34cbe0eedb0d319eff9f7b83e2022bb5a3ab5289a6a8841441076514d0"}, + {file = "pre_commit-2.5.1-py2.py3-none-any.whl", hash = "sha256:c5c8fd4d0e1c363723aaf0a8f9cba0f434c160b48c4028f4bae6d219177945b3"}, + {file = "pre_commit-2.5.1.tar.gz", hash = "sha256:da463cf8f0e257f9af49047ba514f6b90dbd9b4f92f4c8847a3ccd36834874c7"}, ] prompt-toolkit = [ {file = "prompt_toolkit-3.0.5-py3-none-any.whl", hash = "sha256:df7e9e63aea609b1da3a65641ceaf5bc7d05e0a04de5bd45d05dbeffbabf9e04"}, @@ -1931,16 +1932,16 @@ pyrsistent = [ {file = "pyrsistent-0.14.11.tar.gz", hash = "sha256:3ca82748918eb65e2d89f222b702277099aca77e34843c5eb9d52451173970e2"}, ] pytest = [ - {file = "pytest-5.4.2-py3-none-any.whl", hash = "sha256:95c710d0a72d91c13fae35dce195633c929c3792f54125919847fdcdf7caa0d3"}, - {file = "pytest-5.4.2.tar.gz", hash = "sha256:eb2b5e935f6a019317e455b6da83dd8650ac9ffd2ee73a7b657a30873d67a698"}, + {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, + {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, ] pytest-asyncio = [ {file = "pytest-asyncio-0.10.0.tar.gz", hash = "sha256:9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf"}, {file = "pytest_asyncio-0.10.0-py3-none-any.whl", hash = "sha256:d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b"}, ] pytest-cov = [ - {file = "pytest-cov-2.9.0.tar.gz", hash = "sha256:b6a814b8ed6247bd81ff47f038511b57fe1ce7f4cc25b9106f1a4b106f1d9322"}, - {file = "pytest_cov-2.9.0-py2.py3-none-any.whl", hash = "sha256:c87dfd8465d865655a8213859f1b4749b43448b5fae465cb981e16d52a811424"}, + {file = "pytest-cov-2.10.0.tar.gz", hash = "sha256:1a629dc9f48e53512fcbfda6b07de490c374b0c83c55ff7a1720b3fccff0ac87"}, + {file = "pytest_cov-2.10.0-py2.py3-none-any.whl", hash = "sha256:6e6d18092dce6fad667cd7020deed816f858ad3b49d5b5e2b1cc1c97a4dba65c"}, ] pytest-html = [ {file = "pytest-html-2.1.1.tar.gz", hash = "sha256:6a4ac391e105e391208e3eb9bd294a60dd336447fd8e1acddff3a6de7f4e57c5"}, @@ -1980,27 +1981,27 @@ pyyaml = [ {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"}, ] regex = [ - {file = "regex-2020.5.14-cp27-cp27m-win32.whl", hash = "sha256:e565569fc28e3ba3e475ec344d87ed3cd8ba2d575335359749298a0899fe122e"}, - {file = "regex-2020.5.14-cp27-cp27m-win_amd64.whl", hash = "sha256:d466967ac8e45244b9dfe302bbe5e3337f8dc4dec8d7d10f5e950d83b140d33a"}, - {file = "regex-2020.5.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:27ff7325b297fb6e5ebb70d10437592433601c423f5acf86e5bc1ee2919b9561"}, - {file = "regex-2020.5.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ea55b80eb0d1c3f1d8d784264a6764f931e172480a2f1868f2536444c5f01e01"}, - {file = "regex-2020.5.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:c9bce6e006fbe771a02bda468ec40ffccbf954803b470a0345ad39c603402577"}, - {file = "regex-2020.5.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:d881c2e657c51d89f02ae4c21d9adbef76b8325fe4d5cf0e9ad62f850f3a98fd"}, - {file = "regex-2020.5.14-cp36-cp36m-win32.whl", hash = "sha256:99568f00f7bf820c620f01721485cad230f3fb28f57d8fbf4a7967ec2e446994"}, - {file = "regex-2020.5.14-cp36-cp36m-win_amd64.whl", hash = "sha256:70c14743320a68c5dac7fc5a0f685be63bc2024b062fe2aaccc4acc3d01b14a1"}, - {file = "regex-2020.5.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a7c37f048ec3920783abab99f8f4036561a174f1314302ccfa4e9ad31cb00eb4"}, - {file = "regex-2020.5.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:89d76ce33d3266173f5be80bd4efcbd5196cafc34100fdab814f9b228dee0fa4"}, - {file = "regex-2020.5.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:51f17abbe973c7673a61863516bdc9c0ef467407a940f39501e786a07406699c"}, - {file = "regex-2020.5.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ce5cc53aa9fbbf6712e92c7cf268274eaff30f6bd12a0754e8133d85a8fb0f5f"}, - {file = "regex-2020.5.14-cp37-cp37m-win32.whl", hash = "sha256:8044d1c085d49673aadb3d7dc20ef5cb5b030c7a4fa253a593dda2eab3059929"}, - {file = "regex-2020.5.14-cp37-cp37m-win_amd64.whl", hash = "sha256:c2062c7d470751b648f1cacc3f54460aebfc261285f14bc6da49c6943bd48bdd"}, - {file = "regex-2020.5.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:329ba35d711e3428db6b45a53b1b13a0a8ba07cbbcf10bbed291a7da45f106c3"}, - {file = "regex-2020.5.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:579ea215c81d18da550b62ff97ee187b99f1b135fd894a13451e00986a080cad"}, - {file = "regex-2020.5.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:3a9394197664e35566242686d84dfd264c07b20f93514e2e09d3c2b3ffdf78fe"}, - {file = "regex-2020.5.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ce367d21f33e23a84fb83a641b3834dd7dd8e9318ad8ff677fbfae5915a239f7"}, - {file = "regex-2020.5.14-cp38-cp38-win32.whl", hash = "sha256:1386e75c9d1574f6aa2e4eb5355374c8e55f9aac97e224a8a5a6abded0f9c927"}, - {file = "regex-2020.5.14-cp38-cp38-win_amd64.whl", hash = "sha256:7e61be8a2900897803c293247ef87366d5df86bf701083b6c43119c7c6c99108"}, - {file = "regex-2020.5.14.tar.gz", hash = "sha256:ce450ffbfec93821ab1fea94779a8440e10cf63819be6e176eb1973a6017aff5"}, + {file = "regex-2020.6.8-cp27-cp27m-win32.whl", hash = "sha256:fbff901c54c22425a5b809b914a3bfaf4b9570eee0e5ce8186ac71eb2025191c"}, + {file = "regex-2020.6.8-cp27-cp27m-win_amd64.whl", hash = "sha256:112e34adf95e45158c597feea65d06a8124898bdeac975c9087fe71b572bd938"}, + {file = "regex-2020.6.8-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:92d8a043a4241a710c1cf7593f5577fbb832cf6c3a00ff3fc1ff2052aff5dd89"}, + {file = "regex-2020.6.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bae83f2a56ab30d5353b47f9b2a33e4aac4de9401fb582b55c42b132a8ac3868"}, + {file = "regex-2020.6.8-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:b2ba0f78b3ef375114856cbdaa30559914d081c416b431f2437f83ce4f8b7f2f"}, + {file = "regex-2020.6.8-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:95fa7726d073c87141f7bbfb04c284901f8328e2d430eeb71b8ffdd5742a5ded"}, + {file = "regex-2020.6.8-cp36-cp36m-win32.whl", hash = "sha256:e3cdc9423808f7e1bb9c2e0bdb1c9dc37b0607b30d646ff6faf0d4e41ee8fee3"}, + {file = "regex-2020.6.8-cp36-cp36m-win_amd64.whl", hash = "sha256:c78e66a922de1c95a208e4ec02e2e5cf0bb83a36ceececc10a72841e53fbf2bd"}, + {file = "regex-2020.6.8-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:08997a37b221a3e27d68ffb601e45abfb0093d39ee770e4257bd2f5115e8cb0a"}, + {file = "regex-2020.6.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2f6f211633ee8d3f7706953e9d3edc7ce63a1d6aad0be5dcee1ece127eea13ae"}, + {file = "regex-2020.6.8-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:55b4c25cbb3b29f8d5e63aeed27b49fa0f8476b0d4e1b3171d85db891938cc3a"}, + {file = "regex-2020.6.8-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:89cda1a5d3e33ec9e231ece7307afc101b5217523d55ef4dc7fb2abd6de71ba3"}, + {file = "regex-2020.6.8-cp37-cp37m-win32.whl", hash = "sha256:690f858d9a94d903cf5cada62ce069b5d93b313d7d05456dbcd99420856562d9"}, + {file = "regex-2020.6.8-cp37-cp37m-win_amd64.whl", hash = "sha256:1700419d8a18c26ff396b3b06ace315b5f2a6e780dad387e4c48717a12a22c29"}, + {file = "regex-2020.6.8-cp38-cp38-manylinux1_i686.whl", hash = "sha256:654cb773b2792e50151f0e22be0f2b6e1c3a04c5328ff1d9d59c0398d37ef610"}, + {file = "regex-2020.6.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:52e1b4bef02f4040b2fd547357a170fc1146e60ab310cdbdd098db86e929b387"}, + {file = "regex-2020.6.8-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:cf59bbf282b627130f5ba68b7fa3abdb96372b24b66bdf72a4920e8153fc7910"}, + {file = "regex-2020.6.8-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:5aaa5928b039ae440d775acea11d01e42ff26e1561c0ffcd3d805750973c6baf"}, + {file = "regex-2020.6.8-cp38-cp38-win32.whl", hash = "sha256:97712e0d0af05febd8ab63d2ef0ab2d0cd9deddf4476f7aa153f76feef4b2754"}, + {file = "regex-2020.6.8-cp38-cp38-win_amd64.whl", hash = "sha256:6ad8663c17db4c5ef438141f99e291c4d4edfeaacc0ce28b5bba2b0bf273d9b5"}, + {file = "regex-2020.6.8.tar.gz", hash = "sha256:e9b64e609d37438f7d6e68c2546d2cb8062f3adb27e6336bc129b51be20773ac"}, ] requests = [ {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, @@ -2042,8 +2043,8 @@ tornado = [ {file = "tornado-6.0.4.tar.gz", hash = "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc"}, ] tqdm = [ - {file = "tqdm-4.46.0-py2.py3-none-any.whl", hash = "sha256:acdafb20f51637ca3954150d0405ff1a7edde0ff19e38fb99a80a66210d2a28f"}, - {file = "tqdm-4.46.0.tar.gz", hash = "sha256:4733c4a10d0f2a4d098d801464bdaf5240c7dadd2a7fde4ee93b0a0efd9fb25e"}, + {file = "tqdm-4.46.1-py2.py3-none-any.whl", hash = "sha256:07c06493f1403c1380b630ae3dcbe5ae62abcf369a93bbc052502279f189ab8c"}, + {file = "tqdm-4.46.1.tar.gz", hash = "sha256:cd140979c2bebd2311dfb14781d8f19bd5a9debb92dcab9f6ef899c987fcf71f"}, ] traitlets = [ {file = "traitlets-4.3.3-py2.py3-none-any.whl", hash = "sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44"}, @@ -2093,12 +2094,12 @@ uvloop = [ {file = "uvloop-0.14.0.tar.gz", hash = "sha256:123ac9c0c7dd71464f58f1b4ee0bbd81285d96cdda8bc3519281b8973e3a461e"}, ] virtualenv = [ - {file = "virtualenv-20.0.21-py2.py3-none-any.whl", hash = "sha256:a730548b27366c5e6cbdf6f97406d861cccece2e22275e8e1a757aeff5e00c70"}, - {file = "virtualenv-20.0.21.tar.gz", hash = "sha256:a116629d4e7f4d03433b8afa27f43deba09d48bc48f5ecefa4f015a178efb6cf"}, + {file = "virtualenv-20.0.23-py2.py3-none-any.whl", hash = "sha256:ccfb8e1e05a1174f7bd4c163700277ba730496094fe1a58bea9d4ac140a207c8"}, + {file = "virtualenv-20.0.23.tar.gz", hash = "sha256:5102fbf1ec57e80671ef40ed98a84e980a71194cedf30c87c2b25c3a9e0b0107"}, ] wcwidth = [ - {file = "wcwidth-0.1.9-py2.py3-none-any.whl", hash = "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1"}, - {file = "wcwidth-0.1.9.tar.gz", hash = "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"}, + {file = "wcwidth-0.2.4-py2.py3-none-any.whl", hash = "sha256:79375666b9954d4a1a10739315816324c3e73110af9d0e102d906fdb0aec009f"}, + {file = "wcwidth-0.2.4.tar.gz", hash = "sha256:8c6b5b6ee1360b842645f336d9e5d68c55817c26d3050f46b235ef2bc650e48f"}, ] webencodings = [ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, diff --git a/pyproject.toml b/pyproject.toml index 2db33c6c..22efdce3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aiogram" -version = "3.0.0-alpha.4" +version = "3.0.0-alpha.5" description = "Modern and fully asynchronous framework for Telegram Bot API" authors = ["Alex Root Junior "] license = "MIT" diff --git a/tests/mocked_bot.py b/tests/mocked_bot.py index 9ee5731c..03242388 100644 --- a/tests/mocked_bot.py +++ b/tests/mocked_bot.py @@ -5,6 +5,7 @@ from aiogram import Bot from aiogram.api.client.session.base import BaseSession from aiogram.api.methods import TelegramMethod from aiogram.api.methods.base import Request, Response, T +from aiogram.api.types import UNSET class MockedSession(BaseSession): @@ -23,7 +24,9 @@ class MockedSession(BaseSession): async def close(self): pass - async def make_request(self, token: str, method: TelegramMethod[T]) -> T: + async def make_request( + self, token: str, method: TelegramMethod[T], timeout: Optional[int] = UNSET + ) -> T: self.requests.append(method.build_request()) response: Response[T] = self.responses.pop() self.raise_for_status(response) diff --git a/tests/test_api/test_client/test_session/test_base_session.py b/tests/test_api/test_client/test_session/test_base_session.py index 3ac1254b..42dfedf7 100644 --- a/tests/test_api/test_client/test_session/test_base_session.py +++ b/tests/test_api/test_client/test_session/test_base_session.py @@ -1,12 +1,13 @@ import datetime import json -from typing import AsyncContextManager, AsyncGenerator +from typing import AsyncContextManager, AsyncGenerator, Optional import pytest from aiogram.api.client.session.base import BaseSession, T from aiogram.api.client.telegram import PRODUCTION, TelegramAPIServer from aiogram.api.methods import GetMe, Response, TelegramMethod +from aiogram.api.types import UNSET try: from asynctest import CoroutineMock, patch @@ -18,7 +19,7 @@ class CustomSession(BaseSession): async def close(self): pass - async def make_request(self, token: str, method: TelegramMethod[T]) -> None: # type: ignore + async def make_request(self, token: str, method: TelegramMethod[T], timeout: Optional[int] = UNSET) -> None: # type: ignore assert isinstance(token, str) assert isinstance(method, TelegramMethod) diff --git a/tests/test_api/test_types/test_chat_member.py b/tests/test_api/test_types/test_chat_member.py index e5706e5e..bb88e690 100644 --- a/tests/test_api/test_types/test_chat_member.py +++ b/tests/test_api/test_types/test_chat_member.py @@ -7,12 +7,7 @@ user = User(id=42, is_bot=False, first_name="User", last_name=None) class TestChatMember: @pytest.mark.parametrize( - "status,result", - [ - ["administrator", True], - ["creator", True], - ["member", False] - ] + "status,result", [["administrator", True], ["creator", True], ["member", False]] ) def test_is_chat_admin(self, status: str, result: bool): chat_member = ChatMember(user=user, status=status) @@ -26,8 +21,8 @@ class TestChatMember: ["member", True], ["restricted", True], ["kicked", False], - ["left", False] - ] + ["left", False], + ], ) def test_is_chat_member(self, status: str, result: bool): chat_member = ChatMember(user=user, status=status) From 4d631a306983f221ee52557b830c60ead7e909a1 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sun, 14 Jun 2020 17:36:14 +0300 Subject: [PATCH 06/11] Allow to use zero as request timeout --- aiogram/api/client/bot.py | 2 +- aiogram/api/client/session/aiohttp.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/aiogram/api/client/bot.py b/aiogram/api/client/bot.py index 673356d9..50898e22 100644 --- a/aiogram/api/client/bot.py +++ b/aiogram/api/client/bot.py @@ -278,7 +278,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param method: :return: """ - return await self.session.make_request(self.__token, method) + return await self.session.make_request(self.__token, method, timeout=request_timeout) def __hash__(self) -> int: """ diff --git a/aiogram/api/client/session/aiohttp.py b/aiogram/api/client/session/aiohttp.py index 4ecfcea9..92adc896 100644 --- a/aiogram/api/client/session/aiohttp.py +++ b/aiogram/api/client/session/aiohttp.py @@ -134,7 +134,9 @@ class AiohttpSession(BaseSession): url = self.api.api_url(token=token, method=request.method) form = self.build_form_data(request) - async with session.post(url, data=form, timeout=timeout or self.timeout) as resp: + async with session.post( + url, data=form, timeout=self.timeout if timeout is None else timeout + ) as resp: raw_result = await resp.json(loads=self.json_loads) response = call.build_response(raw_result) From f5684aef07ee91dcda1b9c851790ba2f0fc5fe41 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sun, 14 Jun 2020 18:18:29 +0300 Subject: [PATCH 07/11] Update default parse_mode propagation. --- aiogram/api/client/bot.py | 6 +++++- aiogram/api/client/session/aiohttp.py | 10 +++++++--- aiogram/api/client/session/base.py | 17 +++++++++++++++-- aiogram/api/methods/add_sticker_to_set.py | 9 +++++++-- aiogram/api/methods/answer_callback_query.py | 9 +++++++-- aiogram/api/methods/answer_inline_query.py | 11 ++++++++--- .../api/methods/answer_pre_checkout_query.py | 9 +++++++-- aiogram/api/methods/answer_shipping_query.py | 9 +++++++-- aiogram/api/methods/base.py | 15 +++++---------- aiogram/api/methods/create_new_sticker_set.py | 9 +++++++-- aiogram/api/methods/delete_chat_photo.py | 9 +++++++-- aiogram/api/methods/delete_chat_sticker_set.py | 9 +++++++-- aiogram/api/methods/delete_message.py | 9 +++++++-- aiogram/api/methods/delete_sticker_from_set.py | 9 +++++++-- aiogram/api/methods/delete_webhook.py | 9 +++++++-- aiogram/api/methods/edit_message_caption.py | 11 ++++++++--- .../api/methods/edit_message_live_location.py | 9 +++++++-- aiogram/api/methods/edit_message_media.py | 11 ++++++++--- .../api/methods/edit_message_reply_markup.py | 9 +++++++-- aiogram/api/methods/edit_message_text.py | 9 +++++++-- aiogram/api/methods/export_chat_invite_link.py | 9 +++++++-- aiogram/api/methods/forward_message.py | 9 +++++++-- aiogram/api/methods/get_chat.py | 9 +++++++-- aiogram/api/methods/get_chat_administrators.py | 9 +++++++-- aiogram/api/methods/get_chat_member.py | 9 +++++++-- aiogram/api/methods/get_chat_members_count.py | 9 +++++++-- aiogram/api/methods/get_file.py | 9 +++++++-- aiogram/api/methods/get_game_high_scores.py | 9 +++++++-- aiogram/api/methods/get_me.py | 9 +++++++-- aiogram/api/methods/get_my_commands.py | 9 +++++++-- aiogram/api/methods/get_sticker_set.py | 9 +++++++-- aiogram/api/methods/get_updates.py | 9 +++++++-- aiogram/api/methods/get_user_profile_photos.py | 9 +++++++-- aiogram/api/methods/get_webhook_info.py | 9 +++++++-- aiogram/api/methods/kick_chat_member.py | 9 +++++++-- aiogram/api/methods/leave_chat.py | 9 +++++++-- aiogram/api/methods/pin_chat_message.py | 9 +++++++-- aiogram/api/methods/promote_chat_member.py | 9 +++++++-- aiogram/api/methods/restrict_chat_member.py | 9 +++++++-- aiogram/api/methods/send_animation.py | 9 +++++++-- aiogram/api/methods/send_audio.py | 9 +++++++-- aiogram/api/methods/send_chat_action.py | 9 +++++++-- aiogram/api/methods/send_contact.py | 9 +++++++-- aiogram/api/methods/send_dice.py | 9 +++++++-- aiogram/api/methods/send_document.py | 9 +++++++-- aiogram/api/methods/send_game.py | 9 +++++++-- aiogram/api/methods/send_invoice.py | 9 +++++++-- aiogram/api/methods/send_location.py | 9 +++++++-- aiogram/api/methods/send_media_group.py | 11 ++++++++--- aiogram/api/methods/send_message.py | 11 ++++++++--- aiogram/api/methods/send_photo.py | 9 +++++++-- aiogram/api/methods/send_poll.py | 11 ++++++++--- aiogram/api/methods/send_sticker.py | 9 +++++++-- aiogram/api/methods/send_venue.py | 9 +++++++-- aiogram/api/methods/send_video.py | 9 +++++++-- aiogram/api/methods/send_video_note.py | 9 +++++++-- aiogram/api/methods/send_voice.py | 9 +++++++-- .../set_chat_administrator_custom_title.py | 9 +++++++-- aiogram/api/methods/set_chat_description.py | 9 +++++++-- aiogram/api/methods/set_chat_permissions.py | 9 +++++++-- aiogram/api/methods/set_chat_photo.py | 9 +++++++-- aiogram/api/methods/set_chat_sticker_set.py | 9 +++++++-- aiogram/api/methods/set_chat_title.py | 9 +++++++-- aiogram/api/methods/set_game_score.py | 9 +++++++-- aiogram/api/methods/set_my_commands.py | 9 +++++++-- aiogram/api/methods/set_passport_data_errors.py | 9 +++++++-- .../api/methods/set_sticker_position_in_set.py | 9 +++++++-- aiogram/api/methods/set_sticker_set_thumb.py | 9 +++++++-- aiogram/api/methods/set_webhook.py | 9 +++++++-- .../api/methods/stop_message_live_location.py | 9 +++++++-- aiogram/api/methods/stop_poll.py | 9 +++++++-- aiogram/api/methods/unban_chat_member.py | 9 +++++++-- aiogram/api/methods/unpin_chat_message.py | 9 +++++++-- aiogram/api/methods/upload_sticker_file.py | 9 +++++++-- aiogram/dispatcher/dispatcher.py | 2 +- tests/mocked_bot.py | 4 ++-- tests/test_api/test_client/test_bot.py | 7 ++++--- .../test_session/test_aiohttp_session.py | 8 +++++--- .../test_methods/test_answer_inline_query.py | 13 +++++-------- tests/test_api/test_methods/test_base.py | 13 +++++++------ 80 files changed, 552 insertions(+), 185 deletions(-) diff --git a/aiogram/api/client/bot.py b/aiogram/api/client/bot.py index 50898e22..5a78e589 100644 --- a/aiogram/api/client/bot.py +++ b/aiogram/api/client/bot.py @@ -147,6 +147,10 @@ class Bot(ContextInstanceMixin["Bot"]): self.parse_mode = parse_mode self.__token = token + @property + def token(self) -> str: + return self.__token + @property def id(self) -> int: """ @@ -278,7 +282,7 @@ class Bot(ContextInstanceMixin["Bot"]): :param method: :return: """ - return await self.session.make_request(self.__token, method, timeout=request_timeout) + return await self.session.make_request(self, method, timeout=request_timeout) def __hash__(self) -> int: """ diff --git a/aiogram/api/client/session/aiohttp.py b/aiogram/api/client/session/aiohttp.py index 92adc896..53def8f2 100644 --- a/aiogram/api/client/session/aiohttp.py +++ b/aiogram/api/client/session/aiohttp.py @@ -1,6 +1,7 @@ from __future__ import annotations from typing import ( + TYPE_CHECKING, Any, AsyncGenerator, Dict, @@ -20,6 +21,9 @@ from aiogram.api.methods import Request, TelegramMethod from .base import BaseSession +if TYPE_CHECKING: + from ..bot import Bot + T = TypeVar("T") _ProxyBasic = Union[str, Tuple[str, BasicAuth]] _ProxyChain = Iterable[_ProxyBasic] @@ -126,12 +130,12 @@ class AiohttpSession(BaseSession): return form async def make_request( - self, token: str, call: TelegramMethod[T], timeout: Optional[int] = None + self, bot: Bot, call: TelegramMethod[T], timeout: Optional[int] = None ) -> T: session = await self.create_session() - request = call.build_request() - url = self.api.api_url(token=token, method=request.method) + request = call.build_request(bot) + url = self.api.api_url(token=bot.token, method=request.method) form = self.build_form_data(request) async with session.post( diff --git a/aiogram/api/client/session/base.py b/aiogram/api/client/session/base.py index c49d4b5a..69b534f7 100644 --- a/aiogram/api/client/session/base.py +++ b/aiogram/api/client/session/base.py @@ -4,7 +4,17 @@ import abc import datetime import json from types import TracebackType -from typing import Any, AsyncGenerator, Callable, ClassVar, Optional, Type, TypeVar, Union +from typing import ( + TYPE_CHECKING, + Any, + AsyncGenerator, + Callable, + ClassVar, + Optional, + Type, + TypeVar, + Union, +) from aiogram.utils.exceptions import TelegramAPIError @@ -13,6 +23,9 @@ from ...methods import Response, TelegramMethod from ...types import UNSET from ..telegram import PRODUCTION, TelegramAPIServer +if TYPE_CHECKING: + from ..bot import Bot + T = TypeVar("T") _JsonLoads = Callable[..., Any] _JsonDumps = Callable[..., str] @@ -37,7 +50,7 @@ class BaseSession(abc.ABC): @abc.abstractmethod async def make_request( - self, token: str, method: TelegramMethod[T], timeout: Optional[int] = UNSET + self, bot: Bot, method: TelegramMethod[T], timeout: Optional[int] = UNSET ) -> T: # pragma: no cover pass diff --git a/aiogram/api/methods/add_sticker_to_set.py b/aiogram/api/methods/add_sticker_to_set.py index f9c801e3..da4bcd12 100644 --- a/aiogram/api/methods/add_sticker_to_set.py +++ b/aiogram/api/methods/add_sticker_to_set.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InputFile, MaskPosition from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class AddStickerToSet(TelegramMethod[bool]): """ @@ -34,7 +39,7 @@ class AddStickerToSet(TelegramMethod[bool]): mask_position: Optional[MaskPosition] = None """A JSON-serialized object for position where the mask should be placed on faces""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"png_sticker", "tgs_sticker"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/answer_callback_query.py b/aiogram/api/methods/answer_callback_query.py index f0d8405f..0bbb9b3c 100644 --- a/aiogram/api/methods/answer_callback_query.py +++ b/aiogram/api/methods/answer_callback_query.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class AnswerCallbackQuery(TelegramMethod[bool]): """ @@ -33,7 +38,7 @@ class AnswerCallbackQuery(TelegramMethod[bool]): """The maximum amount of time in seconds that the result of the callback query may be cached client-side. Telegram apps will support caching starting in version 3.14. Defaults to 0.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="answerCallbackQuery", data=data) diff --git a/aiogram/api/methods/answer_inline_query.py b/aiogram/api/methods/answer_inline_query.py index eb8a7138..8f61351d 100644 --- a/aiogram/api/methods/answer_inline_query.py +++ b/aiogram/api/methods/answer_inline_query.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, List, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import InlineQueryResult from .base import Request, TelegramMethod, prepare_parse_mode +if TYPE_CHECKING: + from ..client.bot import Bot + class AnswerInlineQuery(TelegramMethod[bool]): """ @@ -36,8 +41,8 @@ class AnswerInlineQuery(TelegramMethod[bool]): """Deep-linking parameter for the /start message sent to the bot when user presses the switch button. 1-64 characters, only A-Z, a-z, 0-9, _ and - are allowed.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() - prepare_parse_mode(data["results"]) + prepare_parse_mode(bot, data["results"]) return Request(method="answerInlineQuery", data=data) diff --git a/aiogram/api/methods/answer_pre_checkout_query.py b/aiogram/api/methods/answer_pre_checkout_query.py index fae21d5c..1370c7b9 100644 --- a/aiogram/api/methods/answer_pre_checkout_query.py +++ b/aiogram/api/methods/answer_pre_checkout_query.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class AnswerPreCheckoutQuery(TelegramMethod[bool]): """ @@ -26,7 +31,7 @@ class AnswerPreCheckoutQuery(TelegramMethod[bool]): amazing black T-shirts while you were busy filling out your payment details. Please choose a different color or garment!"). Telegram will display this message to the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="answerPreCheckoutQuery", data=data) diff --git a/aiogram/api/methods/answer_shipping_query.py b/aiogram/api/methods/answer_shipping_query.py index 986d8fe6..708adb54 100644 --- a/aiogram/api/methods/answer_shipping_query.py +++ b/aiogram/api/methods/answer_shipping_query.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, List, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import ShippingOption from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class AnswerShippingQuery(TelegramMethod[bool]): """ @@ -27,7 +32,7 @@ class AnswerShippingQuery(TelegramMethod[bool]): impossible to complete the order (e.g. "Sorry, delivery to your desired address is unavailable'). Telegram will display this message to the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="answerShippingQuery", data=data) diff --git a/aiogram/api/methods/base.py b/aiogram/api/methods/base.py index 40f251c0..1ad41445 100644 --- a/aiogram/api/methods/base.py +++ b/aiogram/api/methods/base.py @@ -66,7 +66,7 @@ class TelegramMethod(abc.ABC, BaseModel, Generic[T]): pass @abc.abstractmethod - def build_request(self) -> Request: # pragma: no cover + def build_request(self, bot: Bot) -> Request: # pragma: no cover pass def dict(self, **kwargs: Any) -> Any: @@ -125,7 +125,7 @@ def prepare_media_file(data: Dict[str, Any], files: Dict[str, InputFile]) -> Non data["media"]["media"] = f"attach://{tag}" -def prepare_parse_mode(root: Any, parse_mode_property: str = "parse_mode") -> None: +def prepare_parse_mode(bot: Bot, root: Any, parse_mode_property: str = "parse_mode") -> None: """ Find and set parse_mode with highest priority. @@ -136,14 +136,9 @@ def prepare_parse_mode(root: Any, parse_mode_property: str = "parse_mode") -> No """ if isinstance(root, list): for item in root: - prepare_parse_mode(item, parse_mode_property=parse_mode_property) - return - - if root.get(parse_mode_property, UNSET) is UNSET: - from ..client.bot import Bot - - bot = Bot.get_current(no_error=True) - if bot and bot.parse_mode: + prepare_parse_mode(bot=bot, root=item, parse_mode_property=parse_mode_property) + elif root.get(parse_mode_property, UNSET) is UNSET: + if bot.parse_mode: root[parse_mode_property] = bot.parse_mode else: root[parse_mode_property] = None diff --git a/aiogram/api/methods/create_new_sticker_set.py b/aiogram/api/methods/create_new_sticker_set.py index f495986c..86c843df 100644 --- a/aiogram/api/methods/create_new_sticker_set.py +++ b/aiogram/api/methods/create_new_sticker_set.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InputFile, MaskPosition from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class CreateNewStickerSet(TelegramMethod[bool]): """ @@ -40,7 +45,7 @@ class CreateNewStickerSet(TelegramMethod[bool]): mask_position: Optional[MaskPosition] = None """A JSON-serialized object for position where the mask should be placed on faces""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"png_sticker", "tgs_sticker"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/delete_chat_photo.py b/aiogram/api/methods/delete_chat_photo.py index dc9e075c..3d98b8c8 100644 --- a/aiogram/api/methods/delete_chat_photo.py +++ b/aiogram/api/methods/delete_chat_photo.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class DeleteChatPhoto(TelegramMethod[bool]): """ @@ -18,7 +23,7 @@ class DeleteChatPhoto(TelegramMethod[bool]): """Unique identifier for the target chat or username of the target channel (in the format @channelusername)""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="deleteChatPhoto", data=data) diff --git a/aiogram/api/methods/delete_chat_sticker_set.py b/aiogram/api/methods/delete_chat_sticker_set.py index 45d473c0..0247503b 100644 --- a/aiogram/api/methods/delete_chat_sticker_set.py +++ b/aiogram/api/methods/delete_chat_sticker_set.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class DeleteChatStickerSet(TelegramMethod[bool]): """ @@ -19,7 +24,7 @@ class DeleteChatStickerSet(TelegramMethod[bool]): """Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="deleteChatStickerSet", data=data) diff --git a/aiogram/api/methods/delete_message.py b/aiogram/api/methods/delete_message.py index a38df0c0..a584c496 100644 --- a/aiogram/api/methods/delete_message.py +++ b/aiogram/api/methods/delete_message.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class DeleteMessage(TelegramMethod[bool]): """ @@ -28,7 +33,7 @@ class DeleteMessage(TelegramMethod[bool]): message_id: int """Identifier of the message to delete""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="deleteMessage", data=data) diff --git a/aiogram/api/methods/delete_sticker_from_set.py b/aiogram/api/methods/delete_sticker_from_set.py index 2637c599..6552c20a 100644 --- a/aiogram/api/methods/delete_sticker_from_set.py +++ b/aiogram/api/methods/delete_sticker_from_set.py @@ -1,7 +1,12 @@ -from typing import Any, Dict +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class DeleteStickerFromSet(TelegramMethod[bool]): """ @@ -15,7 +20,7 @@ class DeleteStickerFromSet(TelegramMethod[bool]): sticker: str """File identifier of the sticker""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="deleteStickerFromSet", data=data) diff --git a/aiogram/api/methods/delete_webhook.py b/aiogram/api/methods/delete_webhook.py index 0783974e..a0033407 100644 --- a/aiogram/api/methods/delete_webhook.py +++ b/aiogram/api/methods/delete_webhook.py @@ -1,7 +1,12 @@ -from typing import Any, Dict +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class DeleteWebhook(TelegramMethod[bool]): """ @@ -13,7 +18,7 @@ class DeleteWebhook(TelegramMethod[bool]): __returning__ = bool - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="deleteWebhook", data=data) diff --git a/aiogram/api/methods/edit_message_caption.py b/aiogram/api/methods/edit_message_caption.py index 733c357d..4c506344 100644 --- a/aiogram/api/methods/edit_message_caption.py +++ b/aiogram/api/methods/edit_message_caption.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import UNSET, InlineKeyboardMarkup, Message from .base import Request, TelegramMethod, prepare_parse_mode +if TYPE_CHECKING: + from ..client.bot import Bot + class EditMessageCaption(TelegramMethod[Union[Message, bool]]): """ @@ -28,8 +33,8 @@ class EditMessageCaption(TelegramMethod[Union[Message, bool]]): reply_markup: Optional[InlineKeyboardMarkup] = None """A JSON-serialized object for an inline keyboard.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() - prepare_parse_mode(data) + prepare_parse_mode(bot, data) return Request(method="editMessageCaption", data=data) diff --git a/aiogram/api/methods/edit_message_live_location.py b/aiogram/api/methods/edit_message_live_location.py index ca54c11e..dde98984 100644 --- a/aiogram/api/methods/edit_message_live_location.py +++ b/aiogram/api/methods/edit_message_live_location.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InlineKeyboardMarkup, Message from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class EditMessageLiveLocation(TelegramMethod[Union[Message, bool]]): """ @@ -30,7 +35,7 @@ class EditMessageLiveLocation(TelegramMethod[Union[Message, bool]]): reply_markup: Optional[InlineKeyboardMarkup] = None """A JSON-serialized object for a new inline keyboard.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="editMessageLiveLocation", data=data) diff --git a/aiogram/api/methods/edit_message_media.py b/aiogram/api/methods/edit_message_media.py index 88c43973..1e62a585 100644 --- a/aiogram/api/methods/edit_message_media.py +++ b/aiogram/api/methods/edit_message_media.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InlineKeyboardMarkup, InputFile, InputMedia, Message from .base import Request, TelegramMethod, prepare_media_file, prepare_parse_mode +if TYPE_CHECKING: + from ..client.bot import Bot + class EditMessageMedia(TelegramMethod[Union[Message, bool]]): """ @@ -30,9 +35,9 @@ class EditMessageMedia(TelegramMethod[Union[Message, bool]]): reply_markup: Optional[InlineKeyboardMarkup] = None """A JSON-serialized object for a new inline keyboard.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() - prepare_parse_mode(data["media"]) + prepare_parse_mode(bot, data["media"]) files: Dict[str, InputFile] = {} prepare_media_file(data=data, files=files) diff --git a/aiogram/api/methods/edit_message_reply_markup.py b/aiogram/api/methods/edit_message_reply_markup.py index 49dec7fc..e9a14c2c 100644 --- a/aiogram/api/methods/edit_message_reply_markup.py +++ b/aiogram/api/methods/edit_message_reply_markup.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InlineKeyboardMarkup, Message from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class EditMessageReplyMarkup(TelegramMethod[Union[Message, bool]]): """ @@ -24,7 +29,7 @@ class EditMessageReplyMarkup(TelegramMethod[Union[Message, bool]]): reply_markup: Optional[InlineKeyboardMarkup] = None """A JSON-serialized object for an inline keyboard.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="editMessageReplyMarkup", data=data) diff --git a/aiogram/api/methods/edit_message_text.py b/aiogram/api/methods/edit_message_text.py index 23255e98..49af2cb2 100644 --- a/aiogram/api/methods/edit_message_text.py +++ b/aiogram/api/methods/edit_message_text.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import UNSET, InlineKeyboardMarkup, Message from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class EditMessageText(TelegramMethod[Union[Message, bool]]): """ @@ -30,7 +35,7 @@ class EditMessageText(TelegramMethod[Union[Message, bool]]): reply_markup: Optional[InlineKeyboardMarkup] = None """A JSON-serialized object for an inline keyboard.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="editMessageText", data=data) diff --git a/aiogram/api/methods/export_chat_invite_link.py b/aiogram/api/methods/export_chat_invite_link.py index 923664e0..6398ab2f 100644 --- a/aiogram/api/methods/export_chat_invite_link.py +++ b/aiogram/api/methods/export_chat_invite_link.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class ExportChatInviteLink(TelegramMethod[str]): """ @@ -23,7 +28,7 @@ class ExportChatInviteLink(TelegramMethod[str]): """Unique identifier for the target chat or username of the target channel (in the format @channelusername)""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="exportChatInviteLink", data=data) diff --git a/aiogram/api/methods/forward_message.py b/aiogram/api/methods/forward_message.py index d8082704..7ecab18a 100644 --- a/aiogram/api/methods/forward_message.py +++ b/aiogram/api/methods/forward_message.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import Message from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class ForwardMessage(TelegramMethod[Message]): """ @@ -24,7 +29,7 @@ class ForwardMessage(TelegramMethod[Message]): disable_notification: Optional[bool] = None """Sends the message silently. Users will receive a notification with no sound.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="forwardMessage", data=data) diff --git a/aiogram/api/methods/get_chat.py b/aiogram/api/methods/get_chat.py index be1fe55d..6b6f33ae 100644 --- a/aiogram/api/methods/get_chat.py +++ b/aiogram/api/methods/get_chat.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from ..types import Chat from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetChat(TelegramMethod[Chat]): """ @@ -19,7 +24,7 @@ class GetChat(TelegramMethod[Chat]): """Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getChat", data=data) diff --git a/aiogram/api/methods/get_chat_administrators.py b/aiogram/api/methods/get_chat_administrators.py index 75398f82..2792b08f 100644 --- a/aiogram/api/methods/get_chat_administrators.py +++ b/aiogram/api/methods/get_chat_administrators.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, List, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List, Union from ..types import ChatMember from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetChatAdministrators(TelegramMethod[List[ChatMember]]): """ @@ -20,7 +25,7 @@ class GetChatAdministrators(TelegramMethod[List[ChatMember]]): """Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getChatAdministrators", data=data) diff --git a/aiogram/api/methods/get_chat_member.py b/aiogram/api/methods/get_chat_member.py index 69a1c6a3..731709d9 100644 --- a/aiogram/api/methods/get_chat_member.py +++ b/aiogram/api/methods/get_chat_member.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from ..types import ChatMember from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetChatMember(TelegramMethod[ChatMember]): """ @@ -20,7 +25,7 @@ class GetChatMember(TelegramMethod[ChatMember]): user_id: int """Unique identifier of the target user""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getChatMember", data=data) diff --git a/aiogram/api/methods/get_chat_members_count.py b/aiogram/api/methods/get_chat_members_count.py index 50b4f484..f1418ec9 100644 --- a/aiogram/api/methods/get_chat_members_count.py +++ b/aiogram/api/methods/get_chat_members_count.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetChatMembersCount(TelegramMethod[int]): """ @@ -16,7 +21,7 @@ class GetChatMembersCount(TelegramMethod[int]): """Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getChatMembersCount", data=data) diff --git a/aiogram/api/methods/get_file.py b/aiogram/api/methods/get_file.py index f39f2ebf..fb144ad0 100644 --- a/aiogram/api/methods/get_file.py +++ b/aiogram/api/methods/get_file.py @@ -1,8 +1,13 @@ -from typing import Any, Dict +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict from ..types import File from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetFile(TelegramMethod[File]): """ @@ -22,7 +27,7 @@ class GetFile(TelegramMethod[File]): file_id: str """File identifier to get info about""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getFile", data=data) diff --git a/aiogram/api/methods/get_game_high_scores.py b/aiogram/api/methods/get_game_high_scores.py index 5f1b1bb3..3d672819 100644 --- a/aiogram/api/methods/get_game_high_scores.py +++ b/aiogram/api/methods/get_game_high_scores.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, List, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import GameHighScore from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetGameHighScores(TelegramMethod[List[GameHighScore]]): """ @@ -27,7 +32,7 @@ class GetGameHighScores(TelegramMethod[List[GameHighScore]]): inline_message_id: Optional[str] = None """Required if chat_id and message_id are not specified. Identifier of the inline message""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getGameHighScores", data=data) diff --git a/aiogram/api/methods/get_me.py b/aiogram/api/methods/get_me.py index f12f75fc..a14a4de7 100644 --- a/aiogram/api/methods/get_me.py +++ b/aiogram/api/methods/get_me.py @@ -1,8 +1,13 @@ -from typing import Any, Dict +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict from ..types import User from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetMe(TelegramMethod[User]): """ @@ -14,7 +19,7 @@ class GetMe(TelegramMethod[User]): __returning__ = User - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getMe", data=data) diff --git a/aiogram/api/methods/get_my_commands.py b/aiogram/api/methods/get_my_commands.py index 1e1d8f1f..b865b8ae 100644 --- a/aiogram/api/methods/get_my_commands.py +++ b/aiogram/api/methods/get_my_commands.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, List +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List from ..types import BotCommand from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetMyCommands(TelegramMethod[List[BotCommand]]): """ @@ -14,7 +19,7 @@ class GetMyCommands(TelegramMethod[List[BotCommand]]): __returning__ = List[BotCommand] - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getMyCommands", data=data) diff --git a/aiogram/api/methods/get_sticker_set.py b/aiogram/api/methods/get_sticker_set.py index f929117c..ca09587f 100644 --- a/aiogram/api/methods/get_sticker_set.py +++ b/aiogram/api/methods/get_sticker_set.py @@ -1,8 +1,13 @@ -from typing import Any, Dict +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict from ..types import StickerSet from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetStickerSet(TelegramMethod[StickerSet]): """ @@ -16,7 +21,7 @@ class GetStickerSet(TelegramMethod[StickerSet]): name: str """Name of the sticker set""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getStickerSet", data=data) diff --git a/aiogram/api/methods/get_updates.py b/aiogram/api/methods/get_updates.py index 20ca5a8a..5e03738f 100644 --- a/aiogram/api/methods/get_updates.py +++ b/aiogram/api/methods/get_updates.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, List, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import Update from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetUpdates(TelegramMethod[List[Update]]): """ @@ -37,7 +42,7 @@ class GetUpdates(TelegramMethod[List[Update]]): list to receive all updates regardless of type (default). If not specified, the previous setting will be used.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getUpdates", data=data) diff --git a/aiogram/api/methods/get_user_profile_photos.py b/aiogram/api/methods/get_user_profile_photos.py index def605c0..76fe0573 100644 --- a/aiogram/api/methods/get_user_profile_photos.py +++ b/aiogram/api/methods/get_user_profile_photos.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional from ..types import UserProfilePhotos from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetUserProfilePhotos(TelegramMethod[UserProfilePhotos]): """ @@ -22,7 +27,7 @@ class GetUserProfilePhotos(TelegramMethod[UserProfilePhotos]): """Limits the number of photos to be retrieved. Values between 1-100 are accepted. Defaults to 100.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getUserProfilePhotos", data=data) diff --git a/aiogram/api/methods/get_webhook_info.py b/aiogram/api/methods/get_webhook_info.py index 8a147162..4fa3476a 100644 --- a/aiogram/api/methods/get_webhook_info.py +++ b/aiogram/api/methods/get_webhook_info.py @@ -1,8 +1,13 @@ -from typing import Any, Dict +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict from ..types import WebhookInfo from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class GetWebhookInfo(TelegramMethod[WebhookInfo]): """ @@ -15,7 +20,7 @@ class GetWebhookInfo(TelegramMethod[WebhookInfo]): __returning__ = WebhookInfo - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="getWebhookInfo", data=data) diff --git a/aiogram/api/methods/kick_chat_member.py b/aiogram/api/methods/kick_chat_member.py index 64af64a1..3c6e4a6e 100644 --- a/aiogram/api/methods/kick_chat_member.py +++ b/aiogram/api/methods/kick_chat_member.py @@ -1,8 +1,13 @@ +from __future__ import annotations + import datetime -from typing import Any, Dict, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class KickChatMember(TelegramMethod[bool]): """ @@ -25,7 +30,7 @@ class KickChatMember(TelegramMethod[bool]): """Date when the user will be unbanned, unix time. If user is banned for more than 366 days or less than 30 seconds from the current time they are considered to be banned forever""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="kickChatMember", data=data) diff --git a/aiogram/api/methods/leave_chat.py b/aiogram/api/methods/leave_chat.py index 0827fc88..4505762f 100644 --- a/aiogram/api/methods/leave_chat.py +++ b/aiogram/api/methods/leave_chat.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class LeaveChat(TelegramMethod[bool]): """ @@ -16,7 +21,7 @@ class LeaveChat(TelegramMethod[bool]): """Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="leaveChat", data=data) diff --git a/aiogram/api/methods/pin_chat_message.py b/aiogram/api/methods/pin_chat_message.py index 3f8a442d..f8d30376 100644 --- a/aiogram/api/methods/pin_chat_message.py +++ b/aiogram/api/methods/pin_chat_message.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class PinChatMessage(TelegramMethod[bool]): """ @@ -23,7 +28,7 @@ class PinChatMessage(TelegramMethod[bool]): """Pass True, if it is not necessary to send a notification to all chat members about the new pinned message. Notifications are always disabled in channels.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="pinChatMessage", data=data) diff --git a/aiogram/api/methods/promote_chat_member.py b/aiogram/api/methods/promote_chat_member.py index db32fd5b..10b59765 100644 --- a/aiogram/api/methods/promote_chat_member.py +++ b/aiogram/api/methods/promote_chat_member.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class PromoteChatMember(TelegramMethod[bool]): """ @@ -39,7 +44,7 @@ class PromoteChatMember(TelegramMethod[bool]): privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that were appointed by him)""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="promoteChatMember", data=data) diff --git a/aiogram/api/methods/restrict_chat_member.py b/aiogram/api/methods/restrict_chat_member.py index 05dac3a3..21c06dd0 100644 --- a/aiogram/api/methods/restrict_chat_member.py +++ b/aiogram/api/methods/restrict_chat_member.py @@ -1,9 +1,14 @@ +from __future__ import annotations + import datetime -from typing import Any, Dict, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ChatPermissions from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class RestrictChatMember(TelegramMethod[bool]): """ @@ -28,7 +33,7 @@ class RestrictChatMember(TelegramMethod[bool]): more than 366 days or less than 30 seconds from the current time, they are considered to be restricted forever""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="restrictChatMember", data=data) diff --git a/aiogram/api/methods/send_animation.py b/aiogram/api/methods/send_animation.py index 955ed9e9..00ae7546 100644 --- a/aiogram/api/methods/send_animation.py +++ b/aiogram/api/methods/send_animation.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( UNSET, @@ -11,6 +13,9 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class SendAnimation(TelegramMethod[Message]): """ @@ -59,7 +64,7 @@ class SendAnimation(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"animation", "thumb"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/send_audio.py b/aiogram/api/methods/send_audio.py index ca39408f..dcb58746 100644 --- a/aiogram/api/methods/send_audio.py +++ b/aiogram/api/methods/send_audio.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( UNSET, @@ -11,6 +13,9 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class SendAudio(TelegramMethod[Message]): """ @@ -59,7 +64,7 @@ class SendAudio(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"audio", "thumb"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/send_chat_action.py b/aiogram/api/methods/send_chat_action.py index 7f5710a3..fd1be792 100644 --- a/aiogram/api/methods/send_chat_action.py +++ b/aiogram/api/methods/send_chat_action.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SendChatAction(TelegramMethod[bool]): """ @@ -29,7 +34,7 @@ class SendChatAction(TelegramMethod[bool]): record_audio or upload_audio for audio files, upload_document for general files, find_location for location data, record_video_note or upload_video_note for video notes.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="sendChatAction", data=data) diff --git a/aiogram/api/methods/send_contact.py b/aiogram/api/methods/send_contact.py index b7569804..dee9f6b7 100644 --- a/aiogram/api/methods/send_contact.py +++ b/aiogram/api/methods/send_contact.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( ForceReply, @@ -9,6 +11,9 @@ from ..types import ( ) from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SendContact(TelegramMethod[Message]): """ @@ -40,7 +45,7 @@ class SendContact(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="sendContact", data=data) diff --git a/aiogram/api/methods/send_dice.py b/aiogram/api/methods/send_dice.py index fb767799..c267c549 100644 --- a/aiogram/api/methods/send_dice.py +++ b/aiogram/api/methods/send_dice.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( ForceReply, @@ -9,6 +11,9 @@ from ..types import ( ) from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SendDice(TelegramMethod[Message]): """ @@ -36,7 +41,7 @@ class SendDice(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="sendDice", data=data) diff --git a/aiogram/api/methods/send_document.py b/aiogram/api/methods/send_document.py index b6868135..07c91bf4 100644 --- a/aiogram/api/methods/send_document.py +++ b/aiogram/api/methods/send_document.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( UNSET, @@ -11,6 +13,9 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class SendDocument(TelegramMethod[Message]): """ @@ -52,7 +57,7 @@ class SendDocument(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"document", "thumb"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/send_game.py b/aiogram/api/methods/send_game.py index 9d760555..f3113f6c 100644 --- a/aiogram/api/methods/send_game.py +++ b/aiogram/api/methods/send_game.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional from ..types import InlineKeyboardMarkup, Message from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SendGame(TelegramMethod[Message]): """ @@ -26,7 +31,7 @@ class SendGame(TelegramMethod[Message]): """A JSON-serialized object for an inline keyboard. If empty, one 'Play game_title' button will be shown. If not empty, the first button must launch the game.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="sendGame", data=data) diff --git a/aiogram/api/methods/send_invoice.py b/aiogram/api/methods/send_invoice.py index f66b6a80..e96c903d 100644 --- a/aiogram/api/methods/send_invoice.py +++ b/aiogram/api/methods/send_invoice.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, List, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import InlineKeyboardMarkup, LabeledPrice, Message from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SendInvoice(TelegramMethod[Message]): """ @@ -66,7 +71,7 @@ class SendInvoice(TelegramMethod[Message]): """A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="sendInvoice", data=data) diff --git a/aiogram/api/methods/send_location.py b/aiogram/api/methods/send_location.py index 541a81fc..8be75bd0 100644 --- a/aiogram/api/methods/send_location.py +++ b/aiogram/api/methods/send_location.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( ForceReply, @@ -9,6 +11,9 @@ from ..types import ( ) from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SendLocation(TelegramMethod[Message]): """ @@ -39,7 +44,7 @@ class SendLocation(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="sendLocation", data=data) diff --git a/aiogram/api/methods/send_media_group.py b/aiogram/api/methods/send_media_group.py index 735711dc..9bb05c90 100644 --- a/aiogram/api/methods/send_media_group.py +++ b/aiogram/api/methods/send_media_group.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, List, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union from ..types import InputFile, InputMediaPhoto, InputMediaVideo, Message from .base import Request, TelegramMethod, prepare_input_media, prepare_parse_mode +if TYPE_CHECKING: + from ..client.bot import Bot + class SendMediaGroup(TelegramMethod[List[Message]]): """ @@ -24,9 +29,9 @@ class SendMediaGroup(TelegramMethod[List[Message]]): reply_to_message_id: Optional[int] = None """If the messages are a reply, ID of the original message""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() - prepare_parse_mode(data["media"]) + prepare_parse_mode(bot, data["media"]) files: Dict[str, InputFile] = {} prepare_input_media(data, files) diff --git a/aiogram/api/methods/send_message.py b/aiogram/api/methods/send_message.py index 44cc0fd2..a00aa9bb 100644 --- a/aiogram/api/methods/send_message.py +++ b/aiogram/api/methods/send_message.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( UNSET, @@ -10,6 +12,9 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_parse_mode +if TYPE_CHECKING: + from ..client.bot import Bot + class SendMessage(TelegramMethod[Message]): """ @@ -39,8 +44,8 @@ class SendMessage(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() - prepare_parse_mode(data) + prepare_parse_mode(bot, data) return Request(method="sendMessage", data=data) diff --git a/aiogram/api/methods/send_photo.py b/aiogram/api/methods/send_photo.py index ab37099d..968664d1 100644 --- a/aiogram/api/methods/send_photo.py +++ b/aiogram/api/methods/send_photo.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( UNSET, @@ -11,6 +13,9 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class SendPhoto(TelegramMethod[Message]): """ @@ -43,7 +48,7 @@ class SendPhoto(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"photo"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/send_poll.py b/aiogram/api/methods/send_poll.py index 95ed10ed..341c00d8 100644 --- a/aiogram/api/methods/send_poll.py +++ b/aiogram/api/methods/send_poll.py @@ -1,5 +1,7 @@ +from __future__ import annotations + import datetime -from typing import Any, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union from ..types import ( ForceReply, @@ -10,6 +12,9 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_parse_mode +if TYPE_CHECKING: + from ..client.bot import Bot + class SendPoll(TelegramMethod[Message]): """ @@ -59,8 +64,8 @@ class SendPoll(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() - prepare_parse_mode(data, parse_mode_property="explanation_parse_mode") + prepare_parse_mode(bot, data, parse_mode_property="explanation_parse_mode") return Request(method="sendPoll", data=data) diff --git a/aiogram/api/methods/send_sticker.py b/aiogram/api/methods/send_sticker.py index e110b2f8..835f1f4b 100644 --- a/aiogram/api/methods/send_sticker.py +++ b/aiogram/api/methods/send_sticker.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( ForceReply, @@ -10,6 +12,9 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class SendSticker(TelegramMethod[Message]): """ @@ -38,7 +43,7 @@ class SendSticker(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"sticker"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/send_venue.py b/aiogram/api/methods/send_venue.py index 0e03dc6a..62fa79ad 100644 --- a/aiogram/api/methods/send_venue.py +++ b/aiogram/api/methods/send_venue.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( ForceReply, @@ -9,6 +11,9 @@ from ..types import ( ) from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SendVenue(TelegramMethod[Message]): """ @@ -45,7 +50,7 @@ class SendVenue(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="sendVenue", data=data) diff --git a/aiogram/api/methods/send_video.py b/aiogram/api/methods/send_video.py index 8784d134..e56ae1c8 100644 --- a/aiogram/api/methods/send_video.py +++ b/aiogram/api/methods/send_video.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( UNSET, @@ -11,6 +13,9 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class SendVideo(TelegramMethod[Message]): """ @@ -60,7 +65,7 @@ class SendVideo(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"video", "thumb"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/send_video_note.py b/aiogram/api/methods/send_video_note.py index bb41045a..2722706f 100644 --- a/aiogram/api/methods/send_video_note.py +++ b/aiogram/api/methods/send_video_note.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( ForceReply, @@ -10,6 +12,9 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class SendVideoNote(TelegramMethod[Message]): """ @@ -49,7 +54,7 @@ class SendVideoNote(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"video_note", "thumb"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/send_voice.py b/aiogram/api/methods/send_voice.py index 945c6314..69b0dfbc 100644 --- a/aiogram/api/methods/send_voice.py +++ b/aiogram/api/methods/send_voice.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ( UNSET, @@ -11,6 +13,9 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class SendVoice(TelegramMethod[Message]): """ @@ -49,7 +54,7 @@ class SendVoice(TelegramMethod[Message]): """Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"voice"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/set_chat_administrator_custom_title.py b/aiogram/api/methods/set_chat_administrator_custom_title.py index a153212a..01fe6757 100644 --- a/aiogram/api/methods/set_chat_administrator_custom_title.py +++ b/aiogram/api/methods/set_chat_administrator_custom_title.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SetChatAdministratorCustomTitle(TelegramMethod[bool]): """ @@ -21,7 +26,7 @@ class SetChatAdministratorCustomTitle(TelegramMethod[bool]): custom_title: str """New custom title for the administrator; 0-16 characters, emoji are not allowed""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="setChatAdministratorCustomTitle", data=data) diff --git a/aiogram/api/methods/set_chat_description.py b/aiogram/api/methods/set_chat_description.py index 38c35138..dba7fb7d 100644 --- a/aiogram/api/methods/set_chat_description.py +++ b/aiogram/api/methods/set_chat_description.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SetChatDescription(TelegramMethod[bool]): """ @@ -20,7 +25,7 @@ class SetChatDescription(TelegramMethod[bool]): description: Optional[str] = None """New chat description, 0-255 characters""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="setChatDescription", data=data) diff --git a/aiogram/api/methods/set_chat_permissions.py b/aiogram/api/methods/set_chat_permissions.py index 5e415340..aa314bb1 100644 --- a/aiogram/api/methods/set_chat_permissions.py +++ b/aiogram/api/methods/set_chat_permissions.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from ..types import ChatPermissions from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SetChatPermissions(TelegramMethod[bool]): """ @@ -21,7 +26,7 @@ class SetChatPermissions(TelegramMethod[bool]): permissions: ChatPermissions """New default chat permissions""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="setChatPermissions", data=data) diff --git a/aiogram/api/methods/set_chat_photo.py b/aiogram/api/methods/set_chat_photo.py index 4767edb0..4b1b4d0a 100644 --- a/aiogram/api/methods/set_chat_photo.py +++ b/aiogram/api/methods/set_chat_photo.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from ..types import InputFile from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class SetChatPhoto(TelegramMethod[bool]): """ @@ -21,7 +26,7 @@ class SetChatPhoto(TelegramMethod[bool]): photo: InputFile """New chat photo, uploaded using multipart/form-data""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"photo"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/set_chat_sticker_set.py b/aiogram/api/methods/set_chat_sticker_set.py index b7dc0ed0..7b4aefac 100644 --- a/aiogram/api/methods/set_chat_sticker_set.py +++ b/aiogram/api/methods/set_chat_sticker_set.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SetChatStickerSet(TelegramMethod[bool]): """ @@ -21,7 +26,7 @@ class SetChatStickerSet(TelegramMethod[bool]): sticker_set_name: str """Name of the sticker set to be set as the group sticker set""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="setChatStickerSet", data=data) diff --git a/aiogram/api/methods/set_chat_title.py b/aiogram/api/methods/set_chat_title.py index 8337a1a1..8dfcebc5 100644 --- a/aiogram/api/methods/set_chat_title.py +++ b/aiogram/api/methods/set_chat_title.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SetChatTitle(TelegramMethod[bool]): """ @@ -20,7 +25,7 @@ class SetChatTitle(TelegramMethod[bool]): title: str """New chat title, 1-255 characters""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="setChatTitle", data=data) diff --git a/aiogram/api/methods/set_game_score.py b/aiogram/api/methods/set_game_score.py index 5e5dc397..e9e27f69 100644 --- a/aiogram/api/methods/set_game_score.py +++ b/aiogram/api/methods/set_game_score.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import Message from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SetGameScore(TelegramMethod[Union[Message, bool]]): """ @@ -32,7 +37,7 @@ class SetGameScore(TelegramMethod[Union[Message, bool]]): inline_message_id: Optional[str] = None """Required if chat_id and message_id are not specified. Identifier of the inline message""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="setGameScore", data=data) diff --git a/aiogram/api/methods/set_my_commands.py b/aiogram/api/methods/set_my_commands.py index 97ac9bcb..ee6e488e 100644 --- a/aiogram/api/methods/set_my_commands.py +++ b/aiogram/api/methods/set_my_commands.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, List +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List from ..types import BotCommand from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SetMyCommands(TelegramMethod[bool]): """ @@ -17,7 +22,7 @@ class SetMyCommands(TelegramMethod[bool]): """A JSON-serialized list of bot commands to be set as the list of the bot's commands. At most 100 commands can be specified.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="setMyCommands", data=data) diff --git a/aiogram/api/methods/set_passport_data_errors.py b/aiogram/api/methods/set_passport_data_errors.py index 44753546..98e82068 100644 --- a/aiogram/api/methods/set_passport_data_errors.py +++ b/aiogram/api/methods/set_passport_data_errors.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, List +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List from ..types import PassportElementError from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SetPassportDataErrors(TelegramMethod[bool]): """ @@ -24,7 +29,7 @@ class SetPassportDataErrors(TelegramMethod[bool]): errors: List[PassportElementError] """A JSON-serialized array describing the errors""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="setPassportDataErrors", data=data) diff --git a/aiogram/api/methods/set_sticker_position_in_set.py b/aiogram/api/methods/set_sticker_position_in_set.py index 378a39d3..e4b81b23 100644 --- a/aiogram/api/methods/set_sticker_position_in_set.py +++ b/aiogram/api/methods/set_sticker_position_in_set.py @@ -1,7 +1,12 @@ -from typing import Any, Dict +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class SetStickerPositionInSet(TelegramMethod[bool]): """ @@ -18,7 +23,7 @@ class SetStickerPositionInSet(TelegramMethod[bool]): position: int """New sticker position in the set, zero-based""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="setStickerPositionInSet", data=data) diff --git a/aiogram/api/methods/set_sticker_set_thumb.py b/aiogram/api/methods/set_sticker_set_thumb.py index 5ccd3bf3..15d1959e 100644 --- a/aiogram/api/methods/set_sticker_set_thumb.py +++ b/aiogram/api/methods/set_sticker_set_thumb.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InputFile from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class SetStickerSetThumb(TelegramMethod[bool]): """ @@ -27,7 +32,7 @@ class SetStickerSetThumb(TelegramMethod[bool]): Internet, or upload a new one using multipart/form-data.. Animated sticker set thumbnail can't be uploaded via HTTP URL.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"thumb"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/set_webhook.py b/aiogram/api/methods/set_webhook.py index 7da2d287..c1533595 100644 --- a/aiogram/api/methods/set_webhook.py +++ b/aiogram/api/methods/set_webhook.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, List, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import InputFile from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class SetWebhook(TelegramMethod[bool]): """ @@ -43,7 +48,7 @@ class SetWebhook(TelegramMethod[bool]): list to receive all updates regardless of type (default). If not specified, the previous setting will be used.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"certificate"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/api/methods/stop_message_live_location.py b/aiogram/api/methods/stop_message_live_location.py index f4f17910..552564ce 100644 --- a/aiogram/api/methods/stop_message_live_location.py +++ b/aiogram/api/methods/stop_message_live_location.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InlineKeyboardMarkup, Message from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class StopMessageLiveLocation(TelegramMethod[Union[Message, bool]]): """ @@ -26,7 +31,7 @@ class StopMessageLiveLocation(TelegramMethod[Union[Message, bool]]): reply_markup: Optional[InlineKeyboardMarkup] = None """A JSON-serialized object for a new inline keyboard.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="stopMessageLiveLocation", data=data) diff --git a/aiogram/api/methods/stop_poll.py b/aiogram/api/methods/stop_poll.py index d6be55b9..fb7fca3b 100644 --- a/aiogram/api/methods/stop_poll.py +++ b/aiogram/api/methods/stop_poll.py @@ -1,8 +1,13 @@ -from typing import Any, Dict, Optional, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InlineKeyboardMarkup, Poll from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class StopPoll(TelegramMethod[Poll]): """ @@ -22,7 +27,7 @@ class StopPoll(TelegramMethod[Poll]): reply_markup: Optional[InlineKeyboardMarkup] = None """A JSON-serialized object for a new message inline keyboard.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="stopPoll", data=data) diff --git a/aiogram/api/methods/unban_chat_member.py b/aiogram/api/methods/unban_chat_member.py index 09e6da6f..0a4bb14b 100644 --- a/aiogram/api/methods/unban_chat_member.py +++ b/aiogram/api/methods/unban_chat_member.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class UnbanChatMember(TelegramMethod[bool]): """ @@ -20,7 +25,7 @@ class UnbanChatMember(TelegramMethod[bool]): user_id: int """Unique identifier of the target user""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="unbanChatMember", data=data) diff --git a/aiogram/api/methods/unpin_chat_message.py b/aiogram/api/methods/unpin_chat_message.py index c205884d..5a57ef25 100644 --- a/aiogram/api/methods/unpin_chat_message.py +++ b/aiogram/api/methods/unpin_chat_message.py @@ -1,7 +1,12 @@ -from typing import Any, Dict, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod +if TYPE_CHECKING: + from ..client.bot import Bot + class UnpinChatMessage(TelegramMethod[bool]): """ @@ -18,7 +23,7 @@ class UnpinChatMessage(TelegramMethod[bool]): """Unique identifier for the target chat or username of the target channel (in the format @channelusername)""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() return Request(method="unpinChatMessage", data=data) diff --git a/aiogram/api/methods/upload_sticker_file.py b/aiogram/api/methods/upload_sticker_file.py index 7e806754..0e84e95a 100644 --- a/aiogram/api/methods/upload_sticker_file.py +++ b/aiogram/api/methods/upload_sticker_file.py @@ -1,8 +1,13 @@ -from typing import Any, Dict +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict from ..types import File, InputFile from .base import Request, TelegramMethod, prepare_file +if TYPE_CHECKING: + from ..client.bot import Bot + class UploadStickerFile(TelegramMethod[File]): """ @@ -20,7 +25,7 @@ class UploadStickerFile(TelegramMethod[File]): """PNG image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px.""" - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict(exclude={"png_sticker"}) files: Dict[str, InputFile] = {} diff --git a/aiogram/dispatcher/dispatcher.py b/aiogram/dispatcher/dispatcher.py index 1c4b08aa..699f746d 100644 --- a/aiogram/dispatcher/dispatcher.py +++ b/aiogram/dispatcher/dispatcher.py @@ -219,7 +219,7 @@ class Dispatcher(Router): # TODO: handle exceptions response: Any = process_updates.result() if isinstance(response, TelegramMethod): - request = response.build_request() + request = response.build_request(bot=bot) return request.render_webhook_request() else: diff --git a/tests/mocked_bot.py b/tests/mocked_bot.py index 03242388..f0b1ead6 100644 --- a/tests/mocked_bot.py +++ b/tests/mocked_bot.py @@ -25,9 +25,9 @@ class MockedSession(BaseSession): pass async def make_request( - self, token: str, method: TelegramMethod[T], timeout: Optional[int] = UNSET + self, bot: Bot, method: TelegramMethod[T], timeout: Optional[int] = UNSET ) -> T: - self.requests.append(method.build_request()) + self.requests.append(method.build_request(bot)) response: Response[T] = self.responses.pop() self.raise_for_status(response) return response.result # type: ignore diff --git a/tests/test_api/test_client/test_bot.py b/tests/test_api/test_client/test_bot.py index 675c0dd3..b9dff9e7 100644 --- a/tests/test_api/test_client/test_bot.py +++ b/tests/test_api/test_client/test_bot.py @@ -42,12 +42,13 @@ class TestBot: new_callable=CoroutineMock, ) as mocked_make_request: await bot(method) - mocked_make_request.assert_awaited_with("42:TEST", method) + mocked_make_request.assert_awaited_with(bot, method, timeout=None) @pytest.mark.asyncio async def test_close(self): - bot = Bot("42:TEST", session=AiohttpSession()) - await bot.session.create_session() + session = AiohttpSession() + bot = Bot("42:TEST", session=session) + await session.create_session() with patch( "aiogram.api.client.session.aiohttp.AiohttpSession.close", new_callable=CoroutineMock diff --git a/tests/test_api/test_client/test_session/test_aiohttp_session.py b/tests/test_api/test_client/test_session/test_aiohttp_session.py index e7716f9a..bb89e888 100644 --- a/tests/test_api/test_client/test_session/test_aiohttp_session.py +++ b/tests/test_api/test_client/test_session/test_aiohttp_session.py @@ -5,9 +5,11 @@ import aiohttp_socks import pytest from aresponses import ResponsesMockServer +from aiogram import Bot from aiogram.api.client.session.aiohttp import AiohttpSession from aiogram.api.methods import Request, TelegramMethod from aiogram.api.types import InputFile +from tests.mocked_bot import MockedBot try: from asynctest import CoroutineMock, patch @@ -147,7 +149,7 @@ class TestAiohttpSession: assert isinstance(fields[1][2], BareInputFile) @pytest.mark.asyncio - async def test_make_request(self, aresponses: ResponsesMockServer): + async def test_make_request(self, bot: MockedBot, aresponses: ResponsesMockServer): aresponses.add( aresponses.ANY, "/bot42:TEST/method", @@ -164,14 +166,14 @@ class TestAiohttpSession: class TestMethod(TelegramMethod[int]): __returning__ = int - def build_request(self) -> Request: + def build_request(self, bot: Bot) -> Request: return Request(method="method", data={}) call = TestMethod() with patch( "aiogram.api.client.session.base.BaseSession.raise_for_status" ) as patched_raise_for_status: - result = await session.make_request("42:TEST", call) + result = await session.make_request(bot, call) assert isinstance(result, int) assert result == 42 diff --git a/tests/test_api/test_methods/test_answer_inline_query.py b/tests/test_api/test_methods/test_answer_inline_query.py index 84c0a05e..950502c9 100644 --- a/tests/test_api/test_methods/test_answer_inline_query.py +++ b/tests/test_api/test_methods/test_answer_inline_query.py @@ -29,17 +29,14 @@ class TestAnswerInlineQuery: assert request.method == "answerInlineQuery" assert response == prepare_result.result - def test_parse_mode(self): + def test_parse_mode(self, bot: MockedBot): query = AnswerInlineQuery( inline_query_id="query id", results=[InlineQueryResultPhoto(id="result id", photo_url="photo", thumb_url="thumb")], ) - request = query.build_request() + request = query.build_request(bot) assert request.data["results"][0]["parse_mode"] is None - token = Bot.set_current(Bot(token="42:TEST", parse_mode="HTML")) - try: - request = query.build_request() - assert request.data["results"][0]["parse_mode"] == "HTML" - finally: - Bot.reset_current(token) + new_bot = Bot(token="42:TEST", parse_mode="HTML") + request = query.build_request(new_bot) + assert request.data["results"][0]["parse_mode"] == "HTML" diff --git a/tests/test_api/test_methods/test_base.py b/tests/test_api/test_methods/test_base.py index e3627d54..3fd46078 100644 --- a/tests/test_api/test_methods/test_base.py +++ b/tests/test_api/test_methods/test_base.py @@ -4,6 +4,7 @@ import pytest from aiogram import Bot from aiogram.api.methods.base import prepare_parse_mode +from tests.mocked_bot import MockedBot class TestPrepareFile: @@ -35,19 +36,19 @@ class TestPrepareParseMode: ) @pytest.mark.asyncio async def test_default_parse_mode( - self, parse_mode: str, data: Dict[str, str], result: Optional[str] + self, bot: MockedBot, parse_mode: str, data: Dict[str, str], result: Optional[str] ): async with Bot(token="42:TEST", parse_mode=parse_mode).context() as bot: assert bot.parse_mode == parse_mode - prepare_parse_mode(data) + prepare_parse_mode(bot, data) assert data.get("parse_mode") == result @pytest.mark.asyncio async def test_list(self): data = [{}] * 2 data.append({"parse_mode": "HTML"}) - async with Bot(token="42:TEST", parse_mode="Markdown").context(): - prepare_parse_mode(data) + bot = Bot(token="42:TEST", parse_mode="Markdown") + prepare_parse_mode(bot, data) assert isinstance(data, list) assert len(data) == 3 @@ -56,7 +57,7 @@ class TestPrepareParseMode: assert data[1]["parse_mode"] == "Markdown" assert data[2]["parse_mode"] == "HTML" - def test_bot_not_in_context(self): + def test_bot_not_in_context(self, bot: MockedBot): data = {} - prepare_parse_mode(data) + prepare_parse_mode(bot, data) assert data["parse_mode"] is None From 3aa68a93d1af4b0de15ef9b8339117cf39916acd Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sun, 14 Jun 2020 18:21:54 +0300 Subject: [PATCH 08/11] Fix coverage --- aiogram/api/client/session/aiohttp.py | 2 +- aiogram/api/client/session/base.py | 2 +- aiogram/api/methods/add_sticker_to_set.py | 2 +- aiogram/api/methods/answer_callback_query.py | 2 +- aiogram/api/methods/answer_inline_query.py | 2 +- aiogram/api/methods/answer_pre_checkout_query.py | 2 +- aiogram/api/methods/answer_shipping_query.py | 2 +- aiogram/api/methods/create_new_sticker_set.py | 2 +- aiogram/api/methods/delete_chat_photo.py | 2 +- aiogram/api/methods/delete_chat_sticker_set.py | 2 +- aiogram/api/methods/delete_message.py | 2 +- aiogram/api/methods/delete_sticker_from_set.py | 2 +- aiogram/api/methods/delete_webhook.py | 2 +- aiogram/api/methods/edit_message_caption.py | 2 +- aiogram/api/methods/edit_message_live_location.py | 2 +- aiogram/api/methods/edit_message_media.py | 2 +- aiogram/api/methods/edit_message_reply_markup.py | 2 +- aiogram/api/methods/edit_message_text.py | 2 +- aiogram/api/methods/export_chat_invite_link.py | 2 +- aiogram/api/methods/forward_message.py | 2 +- aiogram/api/methods/get_chat.py | 2 +- aiogram/api/methods/get_chat_administrators.py | 2 +- aiogram/api/methods/get_chat_member.py | 2 +- aiogram/api/methods/get_chat_members_count.py | 2 +- aiogram/api/methods/get_file.py | 2 +- aiogram/api/methods/get_game_high_scores.py | 2 +- aiogram/api/methods/get_me.py | 2 +- aiogram/api/methods/get_my_commands.py | 2 +- aiogram/api/methods/get_sticker_set.py | 2 +- aiogram/api/methods/get_updates.py | 2 +- aiogram/api/methods/get_user_profile_photos.py | 2 +- aiogram/api/methods/get_webhook_info.py | 2 +- aiogram/api/methods/kick_chat_member.py | 2 +- aiogram/api/methods/leave_chat.py | 2 +- aiogram/api/methods/pin_chat_message.py | 2 +- aiogram/api/methods/promote_chat_member.py | 2 +- aiogram/api/methods/restrict_chat_member.py | 2 +- aiogram/api/methods/send_animation.py | 2 +- aiogram/api/methods/send_audio.py | 2 +- aiogram/api/methods/send_chat_action.py | 2 +- aiogram/api/methods/send_contact.py | 2 +- aiogram/api/methods/send_dice.py | 2 +- aiogram/api/methods/send_document.py | 2 +- aiogram/api/methods/send_game.py | 2 +- aiogram/api/methods/send_invoice.py | 2 +- aiogram/api/methods/send_location.py | 2 +- aiogram/api/methods/send_media_group.py | 2 +- aiogram/api/methods/send_message.py | 2 +- aiogram/api/methods/send_photo.py | 2 +- aiogram/api/methods/send_poll.py | 2 +- aiogram/api/methods/send_sticker.py | 2 +- aiogram/api/methods/send_venue.py | 2 +- aiogram/api/methods/send_video.py | 2 +- aiogram/api/methods/send_video_note.py | 2 +- aiogram/api/methods/send_voice.py | 2 +- aiogram/api/methods/set_chat_administrator_custom_title.py | 2 +- aiogram/api/methods/set_chat_description.py | 2 +- aiogram/api/methods/set_chat_permissions.py | 2 +- aiogram/api/methods/set_chat_photo.py | 2 +- aiogram/api/methods/set_chat_sticker_set.py | 2 +- aiogram/api/methods/set_chat_title.py | 2 +- aiogram/api/methods/set_game_score.py | 2 +- aiogram/api/methods/set_my_commands.py | 2 +- aiogram/api/methods/set_passport_data_errors.py | 2 +- aiogram/api/methods/set_sticker_position_in_set.py | 2 +- aiogram/api/methods/set_sticker_set_thumb.py | 2 +- aiogram/api/methods/set_webhook.py | 2 +- aiogram/api/methods/stop_message_live_location.py | 2 +- aiogram/api/methods/stop_poll.py | 2 +- aiogram/api/methods/unban_chat_member.py | 2 +- aiogram/api/methods/unpin_chat_message.py | 2 +- aiogram/api/methods/upload_sticker_file.py | 2 +- 72 files changed, 72 insertions(+), 72 deletions(-) diff --git a/aiogram/api/client/session/aiohttp.py b/aiogram/api/client/session/aiohttp.py index 53def8f2..1fda8bbf 100644 --- a/aiogram/api/client/session/aiohttp.py +++ b/aiogram/api/client/session/aiohttp.py @@ -21,7 +21,7 @@ from aiogram.api.methods import Request, TelegramMethod from .base import BaseSession -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..bot import Bot T = TypeVar("T") diff --git a/aiogram/api/client/session/base.py b/aiogram/api/client/session/base.py index 69b534f7..d1249733 100644 --- a/aiogram/api/client/session/base.py +++ b/aiogram/api/client/session/base.py @@ -23,7 +23,7 @@ from ...methods import Response, TelegramMethod from ...types import UNSET from ..telegram import PRODUCTION, TelegramAPIServer -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..bot import Bot T = TypeVar("T") diff --git a/aiogram/api/methods/add_sticker_to_set.py b/aiogram/api/methods/add_sticker_to_set.py index da4bcd12..735371e4 100644 --- a/aiogram/api/methods/add_sticker_to_set.py +++ b/aiogram/api/methods/add_sticker_to_set.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InputFile, MaskPosition from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/answer_callback_query.py b/aiogram/api/methods/answer_callback_query.py index 0bbb9b3c..1f407c70 100644 --- a/aiogram/api/methods/answer_callback_query.py +++ b/aiogram/api/methods/answer_callback_query.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/answer_inline_query.py b/aiogram/api/methods/answer_inline_query.py index 8f61351d..c5c2709d 100644 --- a/aiogram/api/methods/answer_inline_query.py +++ b/aiogram/api/methods/answer_inline_query.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import InlineQueryResult from .base import Request, TelegramMethod, prepare_parse_mode -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/answer_pre_checkout_query.py b/aiogram/api/methods/answer_pre_checkout_query.py index 1370c7b9..8ffae74e 100644 --- a/aiogram/api/methods/answer_pre_checkout_query.py +++ b/aiogram/api/methods/answer_pre_checkout_query.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/answer_shipping_query.py b/aiogram/api/methods/answer_shipping_query.py index 708adb54..da79adb5 100644 --- a/aiogram/api/methods/answer_shipping_query.py +++ b/aiogram/api/methods/answer_shipping_query.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import ShippingOption from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/create_new_sticker_set.py b/aiogram/api/methods/create_new_sticker_set.py index 86c843df..e6a222ae 100644 --- a/aiogram/api/methods/create_new_sticker_set.py +++ b/aiogram/api/methods/create_new_sticker_set.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InputFile, MaskPosition from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/delete_chat_photo.py b/aiogram/api/methods/delete_chat_photo.py index 3d98b8c8..8be35986 100644 --- a/aiogram/api/methods/delete_chat_photo.py +++ b/aiogram/api/methods/delete_chat_photo.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/delete_chat_sticker_set.py b/aiogram/api/methods/delete_chat_sticker_set.py index 0247503b..14801ec4 100644 --- a/aiogram/api/methods/delete_chat_sticker_set.py +++ b/aiogram/api/methods/delete_chat_sticker_set.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/delete_message.py b/aiogram/api/methods/delete_message.py index a584c496..da0edce1 100644 --- a/aiogram/api/methods/delete_message.py +++ b/aiogram/api/methods/delete_message.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/delete_sticker_from_set.py b/aiogram/api/methods/delete_sticker_from_set.py index 6552c20a..30ac3d4b 100644 --- a/aiogram/api/methods/delete_sticker_from_set.py +++ b/aiogram/api/methods/delete_sticker_from_set.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/delete_webhook.py b/aiogram/api/methods/delete_webhook.py index a0033407..9242a634 100644 --- a/aiogram/api/methods/delete_webhook.py +++ b/aiogram/api/methods/delete_webhook.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/edit_message_caption.py b/aiogram/api/methods/edit_message_caption.py index 4c506344..3359c45f 100644 --- a/aiogram/api/methods/edit_message_caption.py +++ b/aiogram/api/methods/edit_message_caption.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import UNSET, InlineKeyboardMarkup, Message from .base import Request, TelegramMethod, prepare_parse_mode -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/edit_message_live_location.py b/aiogram/api/methods/edit_message_live_location.py index dde98984..ddd95d74 100644 --- a/aiogram/api/methods/edit_message_live_location.py +++ b/aiogram/api/methods/edit_message_live_location.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InlineKeyboardMarkup, Message from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/edit_message_media.py b/aiogram/api/methods/edit_message_media.py index 1e62a585..db8e344f 100644 --- a/aiogram/api/methods/edit_message_media.py +++ b/aiogram/api/methods/edit_message_media.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InlineKeyboardMarkup, InputFile, InputMedia, Message from .base import Request, TelegramMethod, prepare_media_file, prepare_parse_mode -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/edit_message_reply_markup.py b/aiogram/api/methods/edit_message_reply_markup.py index e9a14c2c..b9973e40 100644 --- a/aiogram/api/methods/edit_message_reply_markup.py +++ b/aiogram/api/methods/edit_message_reply_markup.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InlineKeyboardMarkup, Message from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/edit_message_text.py b/aiogram/api/methods/edit_message_text.py index 49af2cb2..d30fc82e 100644 --- a/aiogram/api/methods/edit_message_text.py +++ b/aiogram/api/methods/edit_message_text.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import UNSET, InlineKeyboardMarkup, Message from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/export_chat_invite_link.py b/aiogram/api/methods/export_chat_invite_link.py index 6398ab2f..b77b01a5 100644 --- a/aiogram/api/methods/export_chat_invite_link.py +++ b/aiogram/api/methods/export_chat_invite_link.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/forward_message.py b/aiogram/api/methods/forward_message.py index 7ecab18a..06f19956 100644 --- a/aiogram/api/methods/forward_message.py +++ b/aiogram/api/methods/forward_message.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import Message from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_chat.py b/aiogram/api/methods/get_chat.py index 6b6f33ae..6131c00d 100644 --- a/aiogram/api/methods/get_chat.py +++ b/aiogram/api/methods/get_chat.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from ..types import Chat from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_chat_administrators.py b/aiogram/api/methods/get_chat_administrators.py index 2792b08f..584d6f9a 100644 --- a/aiogram/api/methods/get_chat_administrators.py +++ b/aiogram/api/methods/get_chat_administrators.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Union from ..types import ChatMember from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_chat_member.py b/aiogram/api/methods/get_chat_member.py index 731709d9..903fd803 100644 --- a/aiogram/api/methods/get_chat_member.py +++ b/aiogram/api/methods/get_chat_member.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from ..types import ChatMember from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_chat_members_count.py b/aiogram/api/methods/get_chat_members_count.py index f1418ec9..9b830af0 100644 --- a/aiogram/api/methods/get_chat_members_count.py +++ b/aiogram/api/methods/get_chat_members_count.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_file.py b/aiogram/api/methods/get_file.py index fb144ad0..9fce6eb0 100644 --- a/aiogram/api/methods/get_file.py +++ b/aiogram/api/methods/get_file.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict from ..types import File from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_game_high_scores.py b/aiogram/api/methods/get_game_high_scores.py index 3d672819..c2dd0671 100644 --- a/aiogram/api/methods/get_game_high_scores.py +++ b/aiogram/api/methods/get_game_high_scores.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import GameHighScore from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_me.py b/aiogram/api/methods/get_me.py index a14a4de7..c9171d47 100644 --- a/aiogram/api/methods/get_me.py +++ b/aiogram/api/methods/get_me.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict from ..types import User from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_my_commands.py b/aiogram/api/methods/get_my_commands.py index b865b8ae..c748cb92 100644 --- a/aiogram/api/methods/get_my_commands.py +++ b/aiogram/api/methods/get_my_commands.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List from ..types import BotCommand from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_sticker_set.py b/aiogram/api/methods/get_sticker_set.py index ca09587f..56e54577 100644 --- a/aiogram/api/methods/get_sticker_set.py +++ b/aiogram/api/methods/get_sticker_set.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict from ..types import StickerSet from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_updates.py b/aiogram/api/methods/get_updates.py index 5e03738f..ffb74c92 100644 --- a/aiogram/api/methods/get_updates.py +++ b/aiogram/api/methods/get_updates.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import Update from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_user_profile_photos.py b/aiogram/api/methods/get_user_profile_photos.py index 76fe0573..bce33116 100644 --- a/aiogram/api/methods/get_user_profile_photos.py +++ b/aiogram/api/methods/get_user_profile_photos.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional from ..types import UserProfilePhotos from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/get_webhook_info.py b/aiogram/api/methods/get_webhook_info.py index 4fa3476a..218569bb 100644 --- a/aiogram/api/methods/get_webhook_info.py +++ b/aiogram/api/methods/get_webhook_info.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict from ..types import WebhookInfo from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/kick_chat_member.py b/aiogram/api/methods/kick_chat_member.py index 3c6e4a6e..45880c4c 100644 --- a/aiogram/api/methods/kick_chat_member.py +++ b/aiogram/api/methods/kick_chat_member.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/leave_chat.py b/aiogram/api/methods/leave_chat.py index 4505762f..7af04143 100644 --- a/aiogram/api/methods/leave_chat.py +++ b/aiogram/api/methods/leave_chat.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/pin_chat_message.py b/aiogram/api/methods/pin_chat_message.py index f8d30376..dbf0d013 100644 --- a/aiogram/api/methods/pin_chat_message.py +++ b/aiogram/api/methods/pin_chat_message.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/promote_chat_member.py b/aiogram/api/methods/promote_chat_member.py index 10b59765..1b4ca625 100644 --- a/aiogram/api/methods/promote_chat_member.py +++ b/aiogram/api/methods/promote_chat_member.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/restrict_chat_member.py b/aiogram/api/methods/restrict_chat_member.py index 21c06dd0..9626e05a 100644 --- a/aiogram/api/methods/restrict_chat_member.py +++ b/aiogram/api/methods/restrict_chat_member.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import ChatPermissions from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_animation.py b/aiogram/api/methods/send_animation.py index 00ae7546..dcb8e91c 100644 --- a/aiogram/api/methods/send_animation.py +++ b/aiogram/api/methods/send_animation.py @@ -13,7 +13,7 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_audio.py b/aiogram/api/methods/send_audio.py index dcb58746..739fadcb 100644 --- a/aiogram/api/methods/send_audio.py +++ b/aiogram/api/methods/send_audio.py @@ -13,7 +13,7 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_chat_action.py b/aiogram/api/methods/send_chat_action.py index fd1be792..bff4283c 100644 --- a/aiogram/api/methods/send_chat_action.py +++ b/aiogram/api/methods/send_chat_action.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_contact.py b/aiogram/api/methods/send_contact.py index dee9f6b7..90c1fd7d 100644 --- a/aiogram/api/methods/send_contact.py +++ b/aiogram/api/methods/send_contact.py @@ -11,7 +11,7 @@ from ..types import ( ) from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_dice.py b/aiogram/api/methods/send_dice.py index c267c549..1b69fed4 100644 --- a/aiogram/api/methods/send_dice.py +++ b/aiogram/api/methods/send_dice.py @@ -11,7 +11,7 @@ from ..types import ( ) from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_document.py b/aiogram/api/methods/send_document.py index 07c91bf4..9ee44b54 100644 --- a/aiogram/api/methods/send_document.py +++ b/aiogram/api/methods/send_document.py @@ -13,7 +13,7 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_game.py b/aiogram/api/methods/send_game.py index f3113f6c..15257073 100644 --- a/aiogram/api/methods/send_game.py +++ b/aiogram/api/methods/send_game.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional from ..types import InlineKeyboardMarkup, Message from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_invoice.py b/aiogram/api/methods/send_invoice.py index e96c903d..fa9f0615 100644 --- a/aiogram/api/methods/send_invoice.py +++ b/aiogram/api/methods/send_invoice.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import InlineKeyboardMarkup, LabeledPrice, Message from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_location.py b/aiogram/api/methods/send_location.py index 8be75bd0..76cdda91 100644 --- a/aiogram/api/methods/send_location.py +++ b/aiogram/api/methods/send_location.py @@ -11,7 +11,7 @@ from ..types import ( ) from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_media_group.py b/aiogram/api/methods/send_media_group.py index 9bb05c90..70c804e1 100644 --- a/aiogram/api/methods/send_media_group.py +++ b/aiogram/api/methods/send_media_group.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union from ..types import InputFile, InputMediaPhoto, InputMediaVideo, Message from .base import Request, TelegramMethod, prepare_input_media, prepare_parse_mode -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_message.py b/aiogram/api/methods/send_message.py index a00aa9bb..9dbeaa16 100644 --- a/aiogram/api/methods/send_message.py +++ b/aiogram/api/methods/send_message.py @@ -12,7 +12,7 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_parse_mode -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_photo.py b/aiogram/api/methods/send_photo.py index 968664d1..b35cc165 100644 --- a/aiogram/api/methods/send_photo.py +++ b/aiogram/api/methods/send_photo.py @@ -13,7 +13,7 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_poll.py b/aiogram/api/methods/send_poll.py index 341c00d8..0868d0b2 100644 --- a/aiogram/api/methods/send_poll.py +++ b/aiogram/api/methods/send_poll.py @@ -12,7 +12,7 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_parse_mode -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_sticker.py b/aiogram/api/methods/send_sticker.py index 835f1f4b..a2adbffa 100644 --- a/aiogram/api/methods/send_sticker.py +++ b/aiogram/api/methods/send_sticker.py @@ -12,7 +12,7 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_venue.py b/aiogram/api/methods/send_venue.py index 62fa79ad..e81455e4 100644 --- a/aiogram/api/methods/send_venue.py +++ b/aiogram/api/methods/send_venue.py @@ -11,7 +11,7 @@ from ..types import ( ) from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_video.py b/aiogram/api/methods/send_video.py index e56ae1c8..c9c5acb2 100644 --- a/aiogram/api/methods/send_video.py +++ b/aiogram/api/methods/send_video.py @@ -13,7 +13,7 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_video_note.py b/aiogram/api/methods/send_video_note.py index 2722706f..f3b75574 100644 --- a/aiogram/api/methods/send_video_note.py +++ b/aiogram/api/methods/send_video_note.py @@ -12,7 +12,7 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/send_voice.py b/aiogram/api/methods/send_voice.py index 69b0dfbc..2a464439 100644 --- a/aiogram/api/methods/send_voice.py +++ b/aiogram/api/methods/send_voice.py @@ -13,7 +13,7 @@ from ..types import ( ) from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_chat_administrator_custom_title.py b/aiogram/api/methods/set_chat_administrator_custom_title.py index 01fe6757..e4929c51 100644 --- a/aiogram/api/methods/set_chat_administrator_custom_title.py +++ b/aiogram/api/methods/set_chat_administrator_custom_title.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_chat_description.py b/aiogram/api/methods/set_chat_description.py index dba7fb7d..2a7ac937 100644 --- a/aiogram/api/methods/set_chat_description.py +++ b/aiogram/api/methods/set_chat_description.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_chat_permissions.py b/aiogram/api/methods/set_chat_permissions.py index aa314bb1..f4739c5c 100644 --- a/aiogram/api/methods/set_chat_permissions.py +++ b/aiogram/api/methods/set_chat_permissions.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from ..types import ChatPermissions from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_chat_photo.py b/aiogram/api/methods/set_chat_photo.py index 4b1b4d0a..94e8cf55 100644 --- a/aiogram/api/methods/set_chat_photo.py +++ b/aiogram/api/methods/set_chat_photo.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from ..types import InputFile from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_chat_sticker_set.py b/aiogram/api/methods/set_chat_sticker_set.py index 7b4aefac..7f37c7ff 100644 --- a/aiogram/api/methods/set_chat_sticker_set.py +++ b/aiogram/api/methods/set_chat_sticker_set.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_chat_title.py b/aiogram/api/methods/set_chat_title.py index 8dfcebc5..4b3bd8b4 100644 --- a/aiogram/api/methods/set_chat_title.py +++ b/aiogram/api/methods/set_chat_title.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_game_score.py b/aiogram/api/methods/set_game_score.py index e9e27f69..41d3f054 100644 --- a/aiogram/api/methods/set_game_score.py +++ b/aiogram/api/methods/set_game_score.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import Message from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_my_commands.py b/aiogram/api/methods/set_my_commands.py index ee6e488e..f7fd7b9a 100644 --- a/aiogram/api/methods/set_my_commands.py +++ b/aiogram/api/methods/set_my_commands.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List from ..types import BotCommand from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_passport_data_errors.py b/aiogram/api/methods/set_passport_data_errors.py index 98e82068..280187a9 100644 --- a/aiogram/api/methods/set_passport_data_errors.py +++ b/aiogram/api/methods/set_passport_data_errors.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List from ..types import PassportElementError from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_sticker_position_in_set.py b/aiogram/api/methods/set_sticker_position_in_set.py index e4b81b23..54c27bfd 100644 --- a/aiogram/api/methods/set_sticker_position_in_set.py +++ b/aiogram/api/methods/set_sticker_position_in_set.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_sticker_set_thumb.py b/aiogram/api/methods/set_sticker_set_thumb.py index 15d1959e..67d3e50e 100644 --- a/aiogram/api/methods/set_sticker_set_thumb.py +++ b/aiogram/api/methods/set_sticker_set_thumb.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InputFile from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/set_webhook.py b/aiogram/api/methods/set_webhook.py index c1533595..49c7617d 100644 --- a/aiogram/api/methods/set_webhook.py +++ b/aiogram/api/methods/set_webhook.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional from ..types import InputFile from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/stop_message_live_location.py b/aiogram/api/methods/stop_message_live_location.py index 552564ce..a7677163 100644 --- a/aiogram/api/methods/stop_message_live_location.py +++ b/aiogram/api/methods/stop_message_live_location.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InlineKeyboardMarkup, Message from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/stop_poll.py b/aiogram/api/methods/stop_poll.py index fb7fca3b..81e8ef26 100644 --- a/aiogram/api/methods/stop_poll.py +++ b/aiogram/api/methods/stop_poll.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union from ..types import InlineKeyboardMarkup, Poll from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/unban_chat_member.py b/aiogram/api/methods/unban_chat_member.py index 0a4bb14b..56a30bd6 100644 --- a/aiogram/api/methods/unban_chat_member.py +++ b/aiogram/api/methods/unban_chat_member.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/unpin_chat_message.py b/aiogram/api/methods/unpin_chat_message.py index 5a57ef25..419a7edd 100644 --- a/aiogram/api/methods/unpin_chat_message.py +++ b/aiogram/api/methods/unpin_chat_message.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union from .base import Request, TelegramMethod -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot diff --git a/aiogram/api/methods/upload_sticker_file.py b/aiogram/api/methods/upload_sticker_file.py index 0e84e95a..a5f553e3 100644 --- a/aiogram/api/methods/upload_sticker_file.py +++ b/aiogram/api/methods/upload_sticker_file.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict from ..types import File, InputFile from .base import Request, TelegramMethod, prepare_file -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from ..client.bot import Bot From 360fdfc4d8a94baf47acacc24915a951fbc303bd Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Mon, 15 Jun 2020 23:54:06 +0300 Subject: [PATCH 09/11] Fix parse_mode in Message aliases --- aiogram/api/types/message.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/aiogram/api/types/message.py b/aiogram/api/types/message.py index 589de26e..67470b66 100644 --- a/aiogram/api/types/message.py +++ b/aiogram/api/types/message.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, List, Optional, Union from pydantic import Field from ...utils import helper -from .base import TelegramObject +from .base import UNSET, TelegramObject if TYPE_CHECKING: # pragma: no cover from .animation import Animation @@ -256,7 +256,7 @@ class Message(TelegramObject): height: Optional[int] = None, thumb: Optional[Union[InputFile, str]] = None, caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_notification: Optional[bool] = None, reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] @@ -300,7 +300,7 @@ class Message(TelegramObject): height: Optional[int] = None, thumb: Optional[Union[InputFile, str]] = None, caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_notification: Optional[bool] = None, reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] @@ -340,7 +340,7 @@ class Message(TelegramObject): self, audio: Union[InputFile, str], caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, duration: Optional[int] = None, performer: Optional[str] = None, title: Optional[str] = None, @@ -384,7 +384,7 @@ class Message(TelegramObject): self, audio: Union[InputFile, str], caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, duration: Optional[int] = None, performer: Optional[str] = None, title: Optional[str] = None, @@ -499,7 +499,7 @@ class Message(TelegramObject): document: Union[InputFile, str], thumb: Optional[Union[InputFile, str]] = None, caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_notification: Optional[bool] = None, reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] @@ -534,7 +534,7 @@ class Message(TelegramObject): document: Union[InputFile, str], thumb: Optional[Union[InputFile, str]] = None, caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_notification: Optional[bool] = None, reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] @@ -877,7 +877,7 @@ class Message(TelegramObject): def reply( self, text: str, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_web_page_preview: Optional[bool] = None, disable_notification: Optional[bool] = None, reply_markup: Optional[ @@ -909,7 +909,7 @@ class Message(TelegramObject): def answer( self, text: str, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_web_page_preview: Optional[bool] = None, disable_notification: Optional[bool] = None, reply_markup: Optional[ @@ -942,7 +942,7 @@ class Message(TelegramObject): self, photo: Union[InputFile, str], caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_notification: Optional[bool] = None, reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] @@ -974,7 +974,7 @@ class Message(TelegramObject): self, photo: Union[InputFile, str], caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, disable_notification: Optional[bool] = None, reply_markup: Optional[ Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply] @@ -1011,7 +1011,7 @@ class Message(TelegramObject): allows_multiple_answers: Optional[bool] = None, correct_option_id: Optional[int] = None, explanation: Optional[str] = None, - explanation_parse_mode: Optional[str] = None, + explanation_parse_mode: Optional[str] = UNSET, open_period: Optional[int] = None, close_date: Optional[Union[datetime.datetime, datetime.timedelta, int]] = None, is_closed: Optional[bool] = None, @@ -1067,7 +1067,7 @@ class Message(TelegramObject): allows_multiple_answers: Optional[bool] = None, correct_option_id: Optional[int] = None, explanation: Optional[str] = None, - explanation_parse_mode: Optional[str] = None, + explanation_parse_mode: Optional[str] = UNSET, open_period: Optional[int] = None, close_date: Optional[Union[datetime.datetime, datetime.timedelta, int]] = None, is_closed: Optional[bool] = None, @@ -1308,7 +1308,7 @@ class Message(TelegramObject): height: Optional[int] = None, thumb: Optional[Union[InputFile, str]] = None, caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, supports_streaming: Optional[bool] = None, disable_notification: Optional[bool] = None, reply_markup: Optional[ @@ -1355,7 +1355,7 @@ class Message(TelegramObject): height: Optional[int] = None, thumb: Optional[Union[InputFile, str]] = None, caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, supports_streaming: Optional[bool] = None, disable_notification: Optional[bool] = None, reply_markup: Optional[ @@ -1468,7 +1468,7 @@ class Message(TelegramObject): self, voice: Union[InputFile, str], caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, duration: Optional[int] = None, disable_notification: Optional[bool] = None, reply_markup: Optional[ @@ -1503,7 +1503,7 @@ class Message(TelegramObject): self, voice: Union[InputFile, str], caption: Optional[str] = None, - parse_mode: Optional[str] = None, + parse_mode: Optional[str] = UNSET, duration: Optional[int] = None, disable_notification: Optional[bool] = None, reply_markup: Optional[ From 46d01a6ae707d3517c13fc1dd50fe0d25d823404 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sat, 27 Jun 2020 16:59:21 +0300 Subject: [PATCH 10/11] Fix explanation_parse_mode validation --- aiogram/api/client/bot.py | 2 +- aiogram/api/methods/base.py | 5 +++-- aiogram/api/methods/send_poll.py | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/aiogram/api/client/bot.py b/aiogram/api/client/bot.py index 5a78e589..ce12de07 100644 --- a/aiogram/api/client/bot.py +++ b/aiogram/api/client/bot.py @@ -1214,7 +1214,7 @@ class Bot(ContextInstanceMixin["Bot"]): allows_multiple_answers: Optional[bool] = None, correct_option_id: Optional[int] = None, explanation: Optional[str] = None, - explanation_parse_mode: Optional[str] = None, + explanation_parse_mode: Optional[str] = UNSET, open_period: Optional[int] = None, close_date: Optional[Union[datetime.datetime, datetime.timedelta, int]] = None, is_closed: Optional[bool] = None, diff --git a/aiogram/api/methods/base.py b/aiogram/api/methods/base.py index 1ad41445..dfdfda34 100644 --- a/aiogram/api/methods/base.py +++ b/aiogram/api/methods/base.py @@ -56,8 +56,9 @@ class TelegramMethod(abc.ABC, BaseModel, Generic[T]): a model initialization from `Bot.method_name`, so we must take care of it and remove it before fields validation. """ - if "parse_mode" in values and values["parse_mode"] is UNSET: - values.pop("parse_mode") + for parse_mode_attribute in {"parse_mode", "explanation_parse_mode"}: + if parse_mode_attribute in values and values[parse_mode_attribute] is UNSET: + values.pop(parse_mode_attribute) return values @property diff --git a/aiogram/api/methods/send_poll.py b/aiogram/api/methods/send_poll.py index 0868d0b2..b716a9c8 100644 --- a/aiogram/api/methods/send_poll.py +++ b/aiogram/api/methods/send_poll.py @@ -9,6 +9,7 @@ from ..types import ( Message, ReplyKeyboardMarkup, ReplyKeyboardRemove, + UNSET, ) from .base import Request, TelegramMethod, prepare_parse_mode @@ -44,7 +45,7 @@ class SendPoll(TelegramMethod[Message]): explanation: Optional[str] = None """Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a quiz-style poll, 0-200 characters with at most 2 line feeds after entities parsing""" - explanation_parse_mode: Optional[str] = None + explanation_parse_mode: Optional[str] = UNSET """Mode for parsing entities in the explanation. See formatting options for more details.""" open_period: Optional[int] = None """Amount of time in seconds the poll will be active after creation, 5-600. Can't be used From 6f53f15577e3b05a0268b78efdfb410e95672429 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sat, 27 Jun 2020 16:59:52 +0300 Subject: [PATCH 11/11] Reformat code --- aiogram/api/methods/send_poll.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiogram/api/methods/send_poll.py b/aiogram/api/methods/send_poll.py index b716a9c8..35fa45be 100644 --- a/aiogram/api/methods/send_poll.py +++ b/aiogram/api/methods/send_poll.py @@ -4,12 +4,12 @@ import datetime from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union from ..types import ( + UNSET, ForceReply, InlineKeyboardMarkup, Message, ReplyKeyboardMarkup, ReplyKeyboardRemove, - UNSET, ) from .base import Request, TelegramMethod, prepare_parse_mode