mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-01-24 08:14:14 +03:00
Reduce autocast overhead as much as possible
Rationale: if the user is doing things right, the penalty for being friendly (i.e. autocasting to the right version, like User -> InputPeerUser), should be as little as possible. Removing the redundant type() call to access .SUBCLASS_OF_ID and assuming the user provided a TLObject (through excepting whenever the attribute is not available) is x2 and x4 times faster respectively. Of course, this is a micro-optimization, but I still consider it's good to benefit users doing things right or avoiding redundant calls.
This commit is contained in:
parent
33e50aaee1
commit
e3c56b0d98
|
@ -818,10 +818,12 @@ class TelegramClient(TelegramBareClient):
|
||||||
if isinstance(reply_to, int):
|
if isinstance(reply_to, int):
|
||||||
return reply_to
|
return reply_to
|
||||||
|
|
||||||
if isinstance(reply_to, TLObject) and \
|
try:
|
||||||
type(reply_to).SUBCLASS_OF_ID == 0x790009e3:
|
if reply_to.SUBCLASS_OF_ID == 0x790009e3:
|
||||||
# hex(crc32(b'Message')) = 0x790009e3
|
# hex(crc32(b'Message')) = 0x790009e3
|
||||||
return reply_to.id
|
return reply_to.id
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
raise TypeError('Invalid reply_to type: {}'.format(type(reply_to)))
|
raise TypeError('Invalid reply_to type: {}'.format(type(reply_to)))
|
||||||
|
|
||||||
|
@ -1191,9 +1193,14 @@ class TelegramClient(TelegramBareClient):
|
||||||
"""
|
"""
|
||||||
photo = entity
|
photo = entity
|
||||||
possible_names = []
|
possible_names = []
|
||||||
if not isinstance(entity, TLObject) or type(entity).SUBCLASS_OF_ID in (
|
try:
|
||||||
|
is_entity = entity.SUBCLASS_OF_ID in (
|
||||||
0x2da17977, 0xc5af5d94, 0x1f4661b9, 0xd49a2697
|
0x2da17977, 0xc5af5d94, 0x1f4661b9, 0xd49a2697
|
||||||
):
|
)
|
||||||
|
except AttributeError:
|
||||||
|
return None # Not even a TLObject as attribute access failed
|
||||||
|
|
||||||
|
if is_entity:
|
||||||
# Maybe it is an user or a chat? Or their full versions?
|
# Maybe it is an user or a chat? Or their full versions?
|
||||||
#
|
#
|
||||||
# The hexadecimal numbers above are simply:
|
# The hexadecimal numbers above are simply:
|
||||||
|
@ -1705,14 +1712,13 @@ class TelegramClient(TelegramBareClient):
|
||||||
if isinstance(peer, int):
|
if isinstance(peer, int):
|
||||||
peer = PeerUser(peer)
|
peer = PeerUser(peer)
|
||||||
is_peer = True
|
is_peer = True
|
||||||
|
else:
|
||||||
elif isinstance(peer, TLObject):
|
try:
|
||||||
is_peer = type(peer).SUBCLASS_OF_ID == 0x2d45687 # crc32(b'Peer')
|
is_peer = peer.SUBCLASS_OF_ID == 0x2d45687 # crc32(b'Peer')
|
||||||
if not is_peer:
|
if not is_peer:
|
||||||
try:
|
|
||||||
return utils.get_input_peer(peer)
|
return utils.get_input_peer(peer)
|
||||||
except TypeError:
|
except (AttributeError, TypeError):
|
||||||
pass
|
pass # Attribute if not TLObject, Type if not "casteable"
|
||||||
|
|
||||||
if not is_peer:
|
if not is_peer:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
|
|
|
@ -3,11 +3,9 @@ Utilities for working with the Telegram API itself (such as handy methods
|
||||||
to convert between an entity like an User, Chat, etc. into its Input version)
|
to convert between an entity like an User, Chat, etc. into its Input version)
|
||||||
"""
|
"""
|
||||||
import math
|
import math
|
||||||
|
import re
|
||||||
from mimetypes import add_type, guess_extension
|
from mimetypes import add_type, guess_extension
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
from .tl import TLObject
|
|
||||||
from .tl.types import (
|
from .tl.types import (
|
||||||
Channel, ChannelForbidden, Chat, ChatEmpty, ChatForbidden, ChatFull,
|
Channel, ChannelForbidden, Chat, ChatEmpty, ChatForbidden, ChatFull,
|
||||||
ChatPhoto, InputPeerChannel, InputPeerChat, InputPeerUser, InputPeerEmpty,
|
ChatPhoto, InputPeerChannel, InputPeerChat, InputPeerUser, InputPeerEmpty,
|
||||||
|
@ -25,7 +23,6 @@ from .tl.types import (
|
||||||
InputMediaUploadedPhoto, DocumentAttributeFilename, photos
|
InputMediaUploadedPhoto, DocumentAttributeFilename, photos
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
USERNAME_RE = re.compile(
|
USERNAME_RE = re.compile(
|
||||||
r'@|(?:https?://)?(?:telegram\.(?:me|dog)|t\.me)/(joinchat/)?'
|
r'@|(?:https?://)?(?:telegram\.(?:me|dog)|t\.me)/(joinchat/)?'
|
||||||
)
|
)
|
||||||
|
@ -81,12 +78,12 @@ def _raise_cast_fail(entity, target):
|
||||||
def get_input_peer(entity, allow_self=True):
|
def get_input_peer(entity, allow_self=True):
|
||||||
"""Gets the input peer for the given "entity" (user, chat or channel).
|
"""Gets the input peer for the given "entity" (user, chat or channel).
|
||||||
A TypeError is raised if the given entity isn't a supported type."""
|
A TypeError is raised if the given entity isn't a supported type."""
|
||||||
if not isinstance(entity, TLObject):
|
try:
|
||||||
|
if entity.SUBCLASS_OF_ID == 0xc91c90b6: # crc32(b'InputPeer')
|
||||||
|
return entity
|
||||||
|
except AttributeError:
|
||||||
_raise_cast_fail(entity, 'InputPeer')
|
_raise_cast_fail(entity, 'InputPeer')
|
||||||
|
|
||||||
if type(entity).SUBCLASS_OF_ID == 0xc91c90b6: # crc32(b'InputPeer')
|
|
||||||
return entity
|
|
||||||
|
|
||||||
if isinstance(entity, User):
|
if isinstance(entity, User):
|
||||||
if entity.is_self and allow_self:
|
if entity.is_self and allow_self:
|
||||||
return InputPeerSelf()
|
return InputPeerSelf()
|
||||||
|
@ -123,12 +120,12 @@ def get_input_peer(entity, allow_self=True):
|
||||||
|
|
||||||
def get_input_channel(entity):
|
def get_input_channel(entity):
|
||||||
"""Similar to get_input_peer, but for InputChannel's alone"""
|
"""Similar to get_input_peer, but for InputChannel's alone"""
|
||||||
if not isinstance(entity, TLObject):
|
try:
|
||||||
|
if entity.SUBCLASS_OF_ID == 0x40f202fd: # crc32(b'InputChannel')
|
||||||
|
return entity
|
||||||
|
except AttributeError:
|
||||||
_raise_cast_fail(entity, 'InputChannel')
|
_raise_cast_fail(entity, 'InputChannel')
|
||||||
|
|
||||||
if type(entity).SUBCLASS_OF_ID == 0x40f202fd: # crc32(b'InputChannel')
|
|
||||||
return entity
|
|
||||||
|
|
||||||
if isinstance(entity, (Channel, ChannelForbidden)):
|
if isinstance(entity, (Channel, ChannelForbidden)):
|
||||||
return InputChannel(entity.id, entity.access_hash or 0)
|
return InputChannel(entity.id, entity.access_hash or 0)
|
||||||
|
|
||||||
|
@ -140,12 +137,12 @@ def get_input_channel(entity):
|
||||||
|
|
||||||
def get_input_user(entity):
|
def get_input_user(entity):
|
||||||
"""Similar to get_input_peer, but for InputUser's alone"""
|
"""Similar to get_input_peer, but for InputUser's alone"""
|
||||||
if not isinstance(entity, TLObject):
|
try:
|
||||||
|
if entity.SUBCLASS_OF_ID == 0xe669bf46: # crc32(b'InputUser'):
|
||||||
|
return entity
|
||||||
|
except AttributeError:
|
||||||
_raise_cast_fail(entity, 'InputUser')
|
_raise_cast_fail(entity, 'InputUser')
|
||||||
|
|
||||||
if type(entity).SUBCLASS_OF_ID == 0xe669bf46: # crc32(b'InputUser')
|
|
||||||
return entity
|
|
||||||
|
|
||||||
if isinstance(entity, User):
|
if isinstance(entity, User):
|
||||||
if entity.is_self:
|
if entity.is_self:
|
||||||
return InputUserSelf()
|
return InputUserSelf()
|
||||||
|
@ -169,12 +166,12 @@ def get_input_user(entity):
|
||||||
|
|
||||||
def get_input_document(document):
|
def get_input_document(document):
|
||||||
"""Similar to get_input_peer, but for documents"""
|
"""Similar to get_input_peer, but for documents"""
|
||||||
if not isinstance(document, TLObject):
|
try:
|
||||||
|
if document.SUBCLASS_OF_ID == 0xf33fdb68: # crc32(b'InputDocument'):
|
||||||
|
return document
|
||||||
|
except AttributeError:
|
||||||
_raise_cast_fail(document, 'InputDocument')
|
_raise_cast_fail(document, 'InputDocument')
|
||||||
|
|
||||||
if type(document).SUBCLASS_OF_ID == 0xf33fdb68: # crc32(b'InputDocument')
|
|
||||||
return document
|
|
||||||
|
|
||||||
if isinstance(document, Document):
|
if isinstance(document, Document):
|
||||||
return InputDocument(id=document.id, access_hash=document.access_hash)
|
return InputDocument(id=document.id, access_hash=document.access_hash)
|
||||||
|
|
||||||
|
@ -192,12 +189,12 @@ def get_input_document(document):
|
||||||
|
|
||||||
def get_input_photo(photo):
|
def get_input_photo(photo):
|
||||||
"""Similar to get_input_peer, but for documents"""
|
"""Similar to get_input_peer, but for documents"""
|
||||||
if not isinstance(photo, TLObject):
|
try:
|
||||||
|
if photo.SUBCLASS_OF_ID == 0x846363e0: # crc32(b'InputPhoto'):
|
||||||
|
return photo
|
||||||
|
except AttributeError:
|
||||||
_raise_cast_fail(photo, 'InputPhoto')
|
_raise_cast_fail(photo, 'InputPhoto')
|
||||||
|
|
||||||
if type(photo).SUBCLASS_OF_ID == 0x846363e0: # crc32(b'InputPhoto')
|
|
||||||
return photo
|
|
||||||
|
|
||||||
if isinstance(photo, photos.Photo):
|
if isinstance(photo, photos.Photo):
|
||||||
photo = photo.photo
|
photo = photo.photo
|
||||||
|
|
||||||
|
@ -212,12 +209,12 @@ def get_input_photo(photo):
|
||||||
|
|
||||||
def get_input_geo(geo):
|
def get_input_geo(geo):
|
||||||
"""Similar to get_input_peer, but for geo points"""
|
"""Similar to get_input_peer, but for geo points"""
|
||||||
if not isinstance(geo, TLObject):
|
try:
|
||||||
|
if geo.SUBCLASS_OF_ID == 0x430d225: # crc32(b'InputGeoPoint'):
|
||||||
|
return geo
|
||||||
|
except AttributeError:
|
||||||
_raise_cast_fail(geo, 'InputGeoPoint')
|
_raise_cast_fail(geo, 'InputGeoPoint')
|
||||||
|
|
||||||
if type(geo).SUBCLASS_OF_ID == 0x430d225: # crc32(b'InputGeoPoint')
|
|
||||||
return geo
|
|
||||||
|
|
||||||
if isinstance(geo, GeoPoint):
|
if isinstance(geo, GeoPoint):
|
||||||
return InputGeoPoint(lat=geo.lat, long=geo.long)
|
return InputGeoPoint(lat=geo.lat, long=geo.long)
|
||||||
|
|
||||||
|
@ -239,12 +236,12 @@ def get_input_media(media, user_caption=None, is_photo=False):
|
||||||
If the media is a file location and is_photo is known to be True,
|
If the media is a file location and is_photo is known to be True,
|
||||||
it will be treated as an InputMediaUploadedPhoto.
|
it will be treated as an InputMediaUploadedPhoto.
|
||||||
"""
|
"""
|
||||||
if not isinstance(media, TLObject):
|
try:
|
||||||
|
if media.SUBCLASS_OF_ID == 0xfaf846f4: # crc32(b'InputMedia'):
|
||||||
|
return media
|
||||||
|
except AttributeError:
|
||||||
_raise_cast_fail(media, 'InputMedia')
|
_raise_cast_fail(media, 'InputMedia')
|
||||||
|
|
||||||
if type(media).SUBCLASS_OF_ID == 0xfaf846f4: # crc32(b'InputMedia')
|
|
||||||
return media
|
|
||||||
|
|
||||||
if isinstance(media, MessageMediaPhoto):
|
if isinstance(media, MessageMediaPhoto):
|
||||||
return InputMediaPhoto(
|
return InputMediaPhoto(
|
||||||
id=get_input_photo(media.photo),
|
id=get_input_photo(media.photo),
|
||||||
|
@ -357,15 +354,15 @@ def get_peer_id(peer):
|
||||||
a call to utils.resolve_id(marked_id).
|
a call to utils.resolve_id(marked_id).
|
||||||
"""
|
"""
|
||||||
# First we assert it's a Peer TLObject, or early return for integers
|
# First we assert it's a Peer TLObject, or early return for integers
|
||||||
if not isinstance(peer, TLObject):
|
if isinstance(peer, int):
|
||||||
if isinstance(peer, int):
|
return peer
|
||||||
return peer
|
|
||||||
else:
|
|
||||||
_raise_cast_fail(peer, 'int')
|
|
||||||
|
|
||||||
elif type(peer).SUBCLASS_OF_ID not in {0x2d45687, 0xc91c90b6}:
|
try:
|
||||||
# Not a Peer or an InputPeer, so first get its Input version
|
if peer.SUBCLASS_OF_ID not in (0x2d45687, 0xc91c90b6):
|
||||||
peer = get_input_peer(peer, allow_self=False)
|
# Not a Peer or an InputPeer, so first get its Input version
|
||||||
|
peer = get_input_peer(peer, allow_self=False)
|
||||||
|
except AttributeError:
|
||||||
|
_raise_cast_fail(peer, 'int')
|
||||||
|
|
||||||
# Set the right ID/kind, or raise if the TLObject is not recognised
|
# Set the right ID/kind, or raise if the TLObject is not recognised
|
||||||
if isinstance(peer, (PeerUser, InputPeerUser)):
|
if isinstance(peer, (PeerUser, InputPeerUser)):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user