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:
Lonami Exo 2018-01-19 13:00:17 +01:00
parent 33e50aaee1
commit e3c56b0d98
2 changed files with 56 additions and 53 deletions

View File

@ -818,10 +818,12 @@ class TelegramClient(TelegramBareClient):
if isinstance(reply_to, int):
return reply_to
if isinstance(reply_to, TLObject) and \
type(reply_to).SUBCLASS_OF_ID == 0x790009e3:
# hex(crc32(b'Message')) = 0x790009e3
return reply_to.id
try:
if reply_to.SUBCLASS_OF_ID == 0x790009e3:
# hex(crc32(b'Message')) = 0x790009e3
return reply_to.id
except AttributeError:
pass
raise TypeError('Invalid reply_to type: {}'.format(type(reply_to)))
@ -1191,9 +1193,14 @@ class TelegramClient(TelegramBareClient):
"""
photo = entity
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
):
)
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?
#
# The hexadecimal numbers above are simply:
@ -1705,14 +1712,13 @@ class TelegramClient(TelegramBareClient):
if isinstance(peer, int):
peer = PeerUser(peer)
is_peer = True
elif isinstance(peer, TLObject):
is_peer = type(peer).SUBCLASS_OF_ID == 0x2d45687 # crc32(b'Peer')
if not is_peer:
try:
else:
try:
is_peer = peer.SUBCLASS_OF_ID == 0x2d45687 # crc32(b'Peer')
if not is_peer:
return utils.get_input_peer(peer)
except TypeError:
pass
except (AttributeError, TypeError):
pass # Attribute if not TLObject, Type if not "casteable"
if not is_peer:
raise TypeError(

View File

@ -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)
"""
import math
import re
from mimetypes import add_type, guess_extension
import re
from .tl import TLObject
from .tl.types import (
Channel, ChannelForbidden, Chat, ChatEmpty, ChatForbidden, ChatFull,
ChatPhoto, InputPeerChannel, InputPeerChat, InputPeerUser, InputPeerEmpty,
@ -25,7 +23,6 @@ from .tl.types import (
InputMediaUploadedPhoto, DocumentAttributeFilename, photos
)
USERNAME_RE = re.compile(
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):
"""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."""
if not isinstance(entity, TLObject):
try:
if entity.SUBCLASS_OF_ID == 0xc91c90b6: # crc32(b'InputPeer')
return entity
except AttributeError:
_raise_cast_fail(entity, 'InputPeer')
if type(entity).SUBCLASS_OF_ID == 0xc91c90b6: # crc32(b'InputPeer')
return entity
if isinstance(entity, User):
if entity.is_self and allow_self:
return InputPeerSelf()
@ -123,12 +120,12 @@ def get_input_peer(entity, allow_self=True):
def get_input_channel(entity):
"""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')
if type(entity).SUBCLASS_OF_ID == 0x40f202fd: # crc32(b'InputChannel')
return entity
if isinstance(entity, (Channel, ChannelForbidden)):
return InputChannel(entity.id, entity.access_hash or 0)
@ -140,12 +137,12 @@ def get_input_channel(entity):
def get_input_user(entity):
"""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')
if type(entity).SUBCLASS_OF_ID == 0xe669bf46: # crc32(b'InputUser')
return entity
if isinstance(entity, User):
if entity.is_self:
return InputUserSelf()
@ -169,12 +166,12 @@ def get_input_user(entity):
def get_input_document(document):
"""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')
if type(document).SUBCLASS_OF_ID == 0xf33fdb68: # crc32(b'InputDocument')
return document
if isinstance(document, Document):
return InputDocument(id=document.id, access_hash=document.access_hash)
@ -192,12 +189,12 @@ def get_input_document(document):
def get_input_photo(photo):
"""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')
if type(photo).SUBCLASS_OF_ID == 0x846363e0: # crc32(b'InputPhoto')
return photo
if isinstance(photo, photos.Photo):
photo = photo.photo
@ -212,12 +209,12 @@ def get_input_photo(photo):
def get_input_geo(geo):
"""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')
if type(geo).SUBCLASS_OF_ID == 0x430d225: # crc32(b'InputGeoPoint')
return geo
if isinstance(geo, GeoPoint):
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,
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')
if type(media).SUBCLASS_OF_ID == 0xfaf846f4: # crc32(b'InputMedia')
return media
if isinstance(media, MessageMediaPhoto):
return InputMediaPhoto(
id=get_input_photo(media.photo),
@ -357,15 +354,15 @@ def get_peer_id(peer):
a call to utils.resolve_id(marked_id).
"""
# First we assert it's a Peer TLObject, or early return for integers
if not isinstance(peer, TLObject):
if isinstance(peer, int):
return peer
else:
_raise_cast_fail(peer, 'int')
if isinstance(peer, int):
return peer
elif type(peer).SUBCLASS_OF_ID not in {0x2d45687, 0xc91c90b6}:
# Not a Peer or an InputPeer, so first get its Input version
peer = get_input_peer(peer, allow_self=False)
try:
if peer.SUBCLASS_OF_ID not in (0x2d45687, 0xc91c90b6):
# 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
if isinstance(peer, (PeerUser, InputPeerUser)):