Skip to content

Commit 92ff6a8

Browse files
harshil21deepsource-autofix[bot]Bibo-Joshi
authored
Add __slots__ (python-telegram-bot#2345)
Co-authored-by: deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com> Co-authored-by: Hinrich Mahler <[email protected]>
1 parent cc43aef commit 92ff6a8

251 files changed

Lines changed: 2908 additions & 99 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

telegram/base.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from typing import TYPE_CHECKING, List, Optional, Tuple, Type, TypeVar
2727

2828
from telegram.utils.types import JSONDict
29+
from telegram.utils.deprecate import set_new_attribute_deprecated
2930

3031
if TYPE_CHECKING:
3132
from telegram import Bot
@@ -38,11 +39,19 @@ class TelegramObject:
3839

3940
_id_attrs: Tuple[object, ...] = ()
4041

42+
# Adding slots reduces memory usage & allows for faster attribute access.
43+
# Only instance variables should be added to __slots__.
44+
# We add __dict__ here for backward compatibility & also to avoid repetition for subclasses.
45+
__slots__ = ('__dict__',)
46+
4147
def __str__(self) -> str:
4248
return str(self.to_dict())
4349

4450
def __getitem__(self, item: str) -> object:
45-
return self.__dict__[item]
51+
return getattr(self, item, None)
52+
53+
def __setattr__(self, key: str, value: object) -> None:
54+
set_new_attribute_deprecated(self, key, value)
4655

4756
@staticmethod
4857
def _parse_data(data: Optional[JSONDict]) -> Optional[JSONDict]:
@@ -102,11 +111,16 @@ def to_dict(self) -> JSONDict:
102111
"""
103112
data = {}
104113

105-
for key in iter(self.__dict__):
114+
# We want to get all attributes for the class, using self.__slots__ only includes the
115+
# attributes used by that class itself, and not its superclass(es). Hence we get its MRO
116+
# and then get their attributes. The `[:-2]` slice excludes the `object` class & the
117+
# TelegramObject class itself.
118+
attrs = {attr for cls in self.__class__.__mro__[:-2] for attr in cls.__slots__}
119+
for key in attrs:
106120
if key == 'bot' or key.startswith('_'):
107121
continue
108122

109-
value = self.__dict__[key]
123+
value = getattr(self, key, None)
110124
if value is not None:
111125
if hasattr(value, 'to_dict'):
112126
data[key] = value.to_dict()

telegram/bot.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,18 @@ class Bot(TelegramObject):
158158
159159
"""
160160

161+
__slots__ = (
162+
'token',
163+
'base_url',
164+
'base_file_url',
165+
'private_key',
166+
'defaults',
167+
'_bot',
168+
'_commands',
169+
'_request',
170+
'logger',
171+
)
172+
161173
def __init__(
162174
self,
163175
token: str,
@@ -184,6 +196,7 @@ def __init__(
184196
self._bot: Optional[User] = None
185197
self._commands: Optional[List[BotCommand]] = None
186198
self._request = request or Request()
199+
self.private_key = None
187200
self.logger = logging.getLogger(__name__)
188201

189202
if private_key:
@@ -196,6 +209,12 @@ def __init__(
196209
private_key, password=private_key_password, backend=default_backend()
197210
)
198211

212+
def __setattr__(self, key: str, value: object) -> None:
213+
if issubclass(self.__class__, Bot) and self.__class__ is not Bot:
214+
object.__setattr__(self, key, value)
215+
return
216+
super().__setattr__(key, value)
217+
199218
def _insert_defaults(
200219
self, data: Dict[str, object], timeout: ODVInput[float]
201220
) -> Optional[float]:

telegram/botcommand.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class BotCommand(TelegramObject):
4141
4242
"""
4343

44+
__slots__ = ('description', '_id_attrs', 'command')
45+
4446
def __init__(self, command: str, description: str, **_kwargs: Any):
4547
self.command = command
4648
self.description = description

telegram/callbackquery.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,18 @@ class CallbackQuery(TelegramObject):
8585
8686
"""
8787

88+
__slots__ = (
89+
'bot',
90+
'game_short_name',
91+
'message',
92+
'chat_instance',
93+
'id',
94+
'from_user',
95+
'inline_message_id',
96+
'data',
97+
'_id_attrs',
98+
)
99+
88100
def __init__(
89101
self,
90102
id: str, # pylint: disable=W0622

telegram/chat.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,30 @@ class Chat(TelegramObject):
143143
144144
"""
145145

146+
__slots__ = (
147+
'bio',
148+
'id',
149+
'type',
150+
'last_name',
151+
'bot',
152+
'sticker_set_name',
153+
'slow_mode_delay',
154+
'location',
155+
'first_name',
156+
'permissions',
157+
'invite_link',
158+
'pinned_message',
159+
'description',
160+
'can_set_sticker_set',
161+
'username',
162+
'title',
163+
'photo',
164+
'linked_chat_id',
165+
'all_members_are_administrators',
166+
'message_auto_delete_time',
167+
'_id_attrs',
168+
)
169+
146170
SENDER: ClassVar[str] = constants.CHAT_SENDER
147171
""":const:`telegram.constants.CHAT_SENDER`
148172

telegram/chataction.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@
2020
"""This module contains an object that represents a Telegram ChatAction."""
2121
from typing import ClassVar
2222
from telegram import constants
23+
from telegram.utils.deprecate import set_new_attribute_deprecated
2324

2425

2526
class ChatAction:
2627
"""Helper class to provide constants for different chat actions."""
2728

29+
__slots__ = ('__dict__',) # Adding __dict__ here since it doesn't subclass TGObject
2830
FIND_LOCATION: ClassVar[str] = constants.CHATACTION_FIND_LOCATION
2931
""":const:`telegram.constants.CHATACTION_FIND_LOCATION`"""
3032
RECORD_AUDIO: ClassVar[str] = constants.CHATACTION_RECORD_AUDIO
@@ -65,3 +67,6 @@ class ChatAction:
6567
""":const:`telegram.constants.CHATACTION_UPLOAD_VIDEO`"""
6668
UPLOAD_VIDEO_NOTE: ClassVar[str] = constants.CHATACTION_UPLOAD_VIDEO_NOTE
6769
""":const:`telegram.constants.CHATACTION_UPLOAD_VIDEO_NOTE`"""
70+
71+
def __setattr__(self, key: str, value: object) -> None:
72+
set_new_attribute_deprecated(self, key, value)

telegram/chatinvitelink.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ class ChatInviteLink(TelegramObject):
6060
6161
"""
6262

63+
__slots__ = (
64+
'invite_link',
65+
'creator',
66+
'is_primary',
67+
'is_revoked',
68+
'expire_date',
69+
'member_limit',
70+
'_id_attrs',
71+
)
72+
6373
def __init__(
6474
self,
6575
invite_link: str,

telegram/chatlocation.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class ChatLocation(TelegramObject):
4747
4848
"""
4949

50+
__slots__ = ('location', '_id_attrs', 'address')
51+
5052
def __init__(
5153
self,
5254
location: Location,

telegram/chatmember.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,32 @@ class ChatMember(TelegramObject):
138138
139139
"""
140140

141+
__slots__ = (
142+
'is_member',
143+
'can_restrict_members',
144+
'can_delete_messages',
145+
'custom_title',
146+
'can_be_edited',
147+
'can_post_messages',
148+
'can_send_messages',
149+
'can_edit_messages',
150+
'can_send_media_messages',
151+
'is_anonymous',
152+
'can_add_web_page_previews',
153+
'can_send_other_messages',
154+
'can_invite_users',
155+
'can_send_polls',
156+
'user',
157+
'can_promote_members',
158+
'status',
159+
'can_change_info',
160+
'can_pin_messages',
161+
'can_manage_chat',
162+
'can_manage_voice_chats',
163+
'until_date',
164+
'_id_attrs',
165+
)
166+
141167
ADMINISTRATOR: ClassVar[str] = constants.CHATMEMBER_ADMINISTRATOR
142168
""":const:`telegram.constants.CHATMEMBER_ADMINISTRATOR`"""
143169
CREATOR: ClassVar[str] = constants.CHATMEMBER_CREATOR

telegram/chatmemberupdated.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ class ChatMemberUpdated(TelegramObject):
6262
6363
"""
6464

65+
__slots__ = (
66+
'chat',
67+
'from_user',
68+
'date',
69+
'old_chat_member',
70+
'new_chat_member',
71+
'invite_link',
72+
'_id_attrs',
73+
)
74+
6575
def __init__(
6676
self,
6777
chat: Chat,

0 commit comments

Comments
 (0)