Move update type detecting from Dispatcher to Update (#669)

* move update type detecting to Update

* requested changes

* fix typo

* requested changes

* add docstring

* Update CHANGES/669.misc

Co-authored-by: Alex Root Junior <jroot.junior@gmail.com>

* move mypy hack to utils, add lru_cache configuration

* More accurate description of the exception, thanks @uwinx

* Update CHANGES/669.misc

Co-authored-by: evgfilim1 <evgfilim1@yandex.ru>

* Callable import fix

Co-authored-by: evgfilim1 <evgfilim1@yandex.ru>

Co-authored-by: Alex Root Junior <jroot.junior@gmail.com>
Co-authored-by: evgfilim1 <evgfilim1@yandex.ru>
This commit is contained in:
darksidecat 2021-09-05 23:49:23 +03:00 committed by GitHub
parent 7c0e229301
commit 714ac8896c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 43 deletions

1
CHANGES/669.misc Normal file
View file

@ -0,0 +1 @@
Moved update type detection from Dispatcher to Update object

View file

@ -9,7 +9,8 @@ from typing import Any, AsyncGenerator, Dict, List, Optional, Union
from .. import loggers
from ..client.bot import Bot
from ..methods import GetUpdates, TelegramMethod
from ..types import TelegramObject, Update, User
from ..types import Update, User
from ..types.update import UpdateTypeLookupError
from ..utils.backoff import Backoff, BackoffConfig
from ..utils.exceptions.base import TelegramAPIError
from ..utils.exceptions.network import NetworkError
@ -186,47 +187,10 @@ class Dispatcher(Router):
:param kwargs:
:return:
"""
event: TelegramObject
if update.message:
update_type = "message"
event = update.message
elif update.edited_message:
update_type = "edited_message"
event = update.edited_message
elif update.channel_post:
update_type = "channel_post"
event = update.channel_post
elif update.edited_channel_post:
update_type = "edited_channel_post"
event = update.edited_channel_post
elif update.inline_query:
update_type = "inline_query"
event = update.inline_query
elif update.chosen_inline_result:
update_type = "chosen_inline_result"
event = update.chosen_inline_result
elif update.callback_query:
update_type = "callback_query"
event = update.callback_query
elif update.shipping_query:
update_type = "shipping_query"
event = update.shipping_query
elif update.pre_checkout_query:
update_type = "pre_checkout_query"
event = update.pre_checkout_query
elif update.poll:
update_type = "poll"
event = update.poll
elif update.poll_answer:
update_type = "poll_answer"
event = update.poll_answer
elif update.my_chat_member:
update_type = "my_chat_member"
event = update.my_chat_member
elif update.chat_member:
update_type = "chat_member"
event = update.chat_member
else:
try:
update_type = update.event_type
event = update.event
except UpdateTypeLookupError:
warnings.warn(
"Detected unknown update type.\n"
"Seems like Telegram Bot API was updated and you have "

View file

@ -1,7 +1,8 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from typing import TYPE_CHECKING, Optional, cast
from ..utils.mypy_hacks import lru_cache
from .base import TelegramObject
if TYPE_CHECKING: # pragma: no cover
@ -53,3 +54,52 @@ class Update(TelegramObject):
"""*Optional*. The bot's chat member status was updated in a chat. For private chats, this update is received only when the bot is blocked or unblocked by the user."""
chat_member: Optional[ChatMemberUpdated] = None
"""*Optional*. A chat member's status was updated in a chat. The bot must be an administrator in the chat and must explicitly specify 'chat_member' in the list of *allowed_updates* to receive these updates."""
def __hash__(self) -> int:
return hash((type(self), self.update_id))
@property # type: ignore
@lru_cache()
def event_type(self) -> str:
"""
Detect update type
If update type is unknown, raise UpdateTypeLookupError
:return:
"""
if self.message:
return "message"
if self.edited_message:
return "edited_message"
if self.channel_post:
return "channel_post"
if self.edited_channel_post:
return "edited_channel_post"
if self.inline_query:
return "inline_query"
if self.chosen_inline_result:
return "chosen_inline_result"
if self.callback_query:
return "callback_query"
if self.shipping_query:
return "shipping_query"
if self.pre_checkout_query:
return "pre_checkout_query"
if self.poll:
return "poll"
if self.poll_answer:
return "poll_answer"
if self.my_chat_member:
return "my_chat_member"
if self.chat_member:
return "chat_member"
raise UpdateTypeLookupError("Update does not contain any known event type.")
@property
def event(self) -> TelegramObject:
return cast(TelegramObject, getattr(self, self.event_type))
class UpdateTypeLookupError(LookupError):
"""Update does not contain any known event type."""

View file

@ -0,0 +1,16 @@
import functools
from typing import Callable, TypeVar
T = TypeVar("T")
def lru_cache(maxsize: int = 128, typed: bool = False) -> Callable[[T], T]:
"""
fix: lru_cache annotation doesn't work with a property
this hack is only needed for the property, so type annotations are as they are
"""
def wrapper(func: T) -> T:
return functools.lru_cache(maxsize, typed)(func) # type: ignore
return wrapper