From 531b2a4df799b10f24205f7432f20488fa9be534 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Fri, 23 Feb 2018 13:19:23 +0200 Subject: [PATCH] Hashable TelegramObject --- aiogram/types/audio.py | 8 -------- aiogram/types/auth_widget_data.py | 3 +++ aiogram/types/base.py | 25 +++++++++++++++++++++++++ aiogram/types/callback_query.py | 3 +++ aiogram/types/chat.py | 3 +++ aiogram/types/chat_photo.py | 3 +++ aiogram/types/contact.py | 3 +++ aiogram/types/message_entity.py | 4 ++-- aiogram/types/mixins.py | 3 +++ aiogram/types/sticker.py | 11 ++--------- aiogram/types/user.py | 5 +---- aiogram/types/video.py | 11 ++--------- aiogram/types/video_note.py | 11 ++--------- aiogram/types/voice.py | 11 ++--------- 14 files changed, 54 insertions(+), 50 deletions(-) diff --git a/aiogram/types/audio.py b/aiogram/types/audio.py index 7946c28a..ed323f81 100644 --- a/aiogram/types/audio.py +++ b/aiogram/types/audio.py @@ -15,11 +15,3 @@ class Audio(base.TelegramObject, mixins.Downloadable): title: base.String = fields.Field() mime_type: base.String = fields.Field() file_size: base.Integer = fields.Field() - - def __hash__(self): - return hash(self.file_id) + \ - self.duration + \ - hash(self.performer) + \ - hash(self.title) + \ - hash(self.mime_type) + \ - self.file_size diff --git a/aiogram/types/auth_widget_data.py b/aiogram/types/auth_widget_data.py index 64066437..c117c92e 100644 --- a/aiogram/types/auth_widget_data.py +++ b/aiogram/types/auth_widget_data.py @@ -42,3 +42,6 @@ class AuthWidgetData(base.TelegramObject): result += ' ' result += self.last_name return result + + def __hash__(self): + return self.id diff --git a/aiogram/types/base.py b/aiogram/types/base.py index 60a26485..166a9848 100644 --- a/aiogram/types/base.py +++ b/aiogram/types/base.py @@ -244,3 +244,28 @@ class TelegramObject(metaclass=MetaTelegramObject): """ for _, value in self: yield value + + def __hash__(self): + def _hash(obj): + buf = 0 + if isinstance(obj, list): + for item in obj: + buf += _hash(item) + elif isinstance(obj, dict): + for dict_key, dict_value in obj.items(): + buf += hash(dict_key) + _hash(dict_value) + else: + try: + buf += hash(obj) + except TypeError: # Skip unhashable objects + pass + return buf + + result = 0 + for key, value in sorted(self.values.items()): + result += hash(key) + _hash(value) + + return result + + def __eq__(self, other): + return isinstance(other, self.__class__) and hash(other) == hash(self) diff --git a/aiogram/types/callback_query.py b/aiogram/types/callback_query.py index 72ef1604..51ba1f17 100644 --- a/aiogram/types/callback_query.py +++ b/aiogram/types/callback_query.py @@ -56,3 +56,6 @@ class CallbackQuery(base.TelegramObject): :rtype: :obj:`base.Boolean`""" await self.bot.answer_callback_query(callback_query_id=self.id, text=text, show_alert=show_alert, url=url, cache_time=cache_time) + + def __hash__(self): + return hash(self.id) diff --git a/aiogram/types/chat.py b/aiogram/types/chat.py index a696e90e..1d6db5a9 100644 --- a/aiogram/types/chat.py +++ b/aiogram/types/chat.py @@ -28,6 +28,9 @@ class Chat(base.TelegramObject): sticker_set_name: base.String = fields.Field() can_set_sticker_set: base.Boolean = fields.Field() + def __hash__(self): + return self.id + @property def full_name(self): if self.type == ChatType.PRIVATE: diff --git a/aiogram/types/chat_photo.py b/aiogram/types/chat_photo.py index daac874b..08775d93 100644 --- a/aiogram/types/chat_photo.py +++ b/aiogram/types/chat_photo.py @@ -73,3 +73,6 @@ class ChatPhoto(base.TelegramObject): async def get_big_file(self): return await self.bot.get_file(self.big_file_id) + + def __hash__(self): + return hash(self.small_file_id) + hash(self.big_file_id) diff --git a/aiogram/types/contact.py b/aiogram/types/contact.py index 5f0eed35..842d6044 100644 --- a/aiogram/types/contact.py +++ b/aiogram/types/contact.py @@ -19,3 +19,6 @@ class Contact(base.TelegramObject): if self.last_name is not None: name += ' ' + self.last_name return name + + def __hash__(self): + return hash(self.phone_number) diff --git a/aiogram/types/message_entity.py b/aiogram/types/message_entity.py index 46733f3a..24e6da5f 100644 --- a/aiogram/types/message_entity.py +++ b/aiogram/types/message_entity.py @@ -18,8 +18,8 @@ class MessageEntity(base.TelegramObject): def _apply(self, text, func): return text[:self.offset] + \ - func(text[self.offset:self.offset + self.length]) + \ - text[self.offset + self.length:] + func(text[self.offset:self.offset + self.length]) + \ + text[self.offset + self.length:] def apply_md(self, text): """ diff --git a/aiogram/types/mixins.py b/aiogram/types/mixins.py index 0d0a42f9..396633ad 100644 --- a/aiogram/types/mixins.py +++ b/aiogram/types/mixins.py @@ -44,3 +44,6 @@ class Downloadable: return self else: return await self.bot.get_file(self.file_id) + + def __hash__(self): + return hash(self.file_id) diff --git a/aiogram/types/sticker.py b/aiogram/types/sticker.py index 5b68d458..b2fd7ef6 100644 --- a/aiogram/types/sticker.py +++ b/aiogram/types/sticker.py @@ -1,10 +1,11 @@ from . import base from . import fields +from . import mixins from .mask_position import MaskPosition from .photo_size import PhotoSize -class Sticker(base.TelegramObject): +class Sticker(base.TelegramObject, mixins.Downloadable): """ This object represents a sticker. @@ -18,11 +19,3 @@ class Sticker(base.TelegramObject): set_name: base.String = fields.Field() mask_position: MaskPosition = fields.Field(base=MaskPosition) file_size: base.Integer = fields.Field() - - def __hash__(self): - return self.file_id - - def __eq__(self, other): - if isinstance(other, type(self)): - return other.file_id == self.file_id - return self.file_id == other diff --git a/aiogram/types/user.py b/aiogram/types/user.py index c8864f8d..40e1f7bc 100644 --- a/aiogram/types/user.py +++ b/aiogram/types/user.py @@ -78,10 +78,7 @@ class User(base.TelegramObject): return await self.bot.get_user_profile_photos(self.id, offset, limit) def __hash__(self): - return self.id + \ - hash(self.is_bot) + \ - hash(self.full_name) + \ - (hash(self.username) if self.username else 0) + return self.id def __int__(self): return self.id diff --git a/aiogram/types/video.py b/aiogram/types/video.py index 36fc0f90..bf5187cd 100644 --- a/aiogram/types/video.py +++ b/aiogram/types/video.py @@ -1,9 +1,10 @@ from . import base from . import fields +from . import mixins from .photo_size import PhotoSize -class Video(base.TelegramObject): +class Video(base.TelegramObject, mixins.Downloadable): """ This object represents a video file. @@ -16,11 +17,3 @@ class Video(base.TelegramObject): thumb: PhotoSize = fields.Field(base=PhotoSize) mime_type: base.String = fields.Field() file_size: base.Integer = fields.Field() - - def __hash__(self): - return self.file_id - - def __eq__(self, other): - if isinstance(other, type(self)): - return other.file_id == self.file_id - return self.file_id == other diff --git a/aiogram/types/video_note.py b/aiogram/types/video_note.py index 286ca762..9665b6bc 100644 --- a/aiogram/types/video_note.py +++ b/aiogram/types/video_note.py @@ -1,9 +1,10 @@ from . import base from . import fields +from . import mixins from .photo_size import PhotoSize -class VideoNote(base.TelegramObject): +class VideoNote(base.TelegramObject, mixins.Downloadable): """ This object represents a video message (available in Telegram apps as of v.4.0). @@ -14,11 +15,3 @@ class VideoNote(base.TelegramObject): duration: base.Integer = fields.Field() thumb: PhotoSize = fields.Field(base=PhotoSize) file_size: base.Integer = fields.Field() - - def __hash__(self): - return self.file_id - - def __eq__(self, other): - if isinstance(other, type(self)): - return other.file_id == self.file_id - return self.file_id == other diff --git a/aiogram/types/voice.py b/aiogram/types/voice.py index ba006bec..621f2247 100644 --- a/aiogram/types/voice.py +++ b/aiogram/types/voice.py @@ -1,8 +1,9 @@ from . import base from . import fields +from . import mixins -class Voice(base.TelegramObject): +class Voice(base.TelegramObject, mixins.Downloadable): """ This object represents a voice note. @@ -12,11 +13,3 @@ class Voice(base.TelegramObject): duration: base.Integer = fields.Field() mime_type: base.String = fields.Field() file_size: base.Integer = fields.Field() - - def __hash__(self): - return self.file_id - - def __eq__(self, other): - if isinstance(other, type(self)): - return other.file_id == self.file_id - return self.file_id == other