Add a custom role for TL references and make use of it

This commit is contained in:
Lonami Exo 2018-03-23 21:40:24 +01:00
parent c6d821910e
commit 43c6896481
12 changed files with 212 additions and 134 deletions

View File

@ -17,15 +17,16 @@
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
import os
import re
import os
import sys
sys.path.insert(0, os.path.abspath('.'))
root = os.path.abspath(os.path.join(__file__, os.path.pardir, os.path.pardir))
tl_ref_url = 'https://lonamiwebs.github.io/Telethon'
# -- General configuration ------------------------------------------------
@ -36,7 +37,10 @@ root = os.path.abspath(os.path.join(__file__, os.path.pardir, os.path.pardir))
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc']
extensions = [
'sphinx.ext.autodoc',
'custom_roles'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

View File

@ -0,0 +1,69 @@
from docutils import nodes, utils
from docutils.parsers.rst.roles import set_classes
def make_link_node(rawtext, app, name, options):
"""
Create a link to the TL reference.
:param rawtext: Text being replaced with link node.
:param app: Sphinx application context
:param name: Name of the object to link to
:param options: Options dictionary passed to role func.
"""
try:
base = app.config.tl_ref_url
if not base:
raise AttributeError
except AttributeError as e:
raise ValueError('tl_ref_url config value is not set') from e
if base[-1] != '/':
base += '/'
set_classes(options)
node = nodes.reference(rawtext, utils.unescape(name),
refuri='{}?q={}'.format(base, name),
**options)
return node
def tl_role(name, rawtext, text, lineno, inliner, options=None, content=None):
"""
Link to the TL reference.
Returns 2 part tuple containing list of nodes to insert into the
document and a list of system messages. Both are allowed to be empty.
:param name: The role name used in the document.
:param rawtext: The entire markup snippet, with role.
:param text: The text marked with the role.
:param lineno: The line number where rawtext appears in the input.
:param inliner: The inliner instance that called us.
:param options: Directive options for customization.
:param content: The directive content for customization.
"""
if options is None:
options = {}
if content is None:
content = []
# TODO Report error on type not found?
# Usage:
# msg = inliner.reporter.error(..., line=lineno)
# return [inliner.problematic(rawtext, rawtext, msg)], [msg]
app = inliner.document.settings.env.app
node = make_link_node(rawtext, app, text, options)
return [node], []
def setup(app):
"""
Install the plugin.
:param app: Sphinx application context.
"""
app.info('Initializing TL reference plugin')
app.add_role('tl', tl_role)
app.add_config_value('tl_ref_url', None, 'env')
return

View File

@ -25,7 +25,7 @@ You should also refer to the documentation to see what the objects
from a common type, and that's the reason for this distinction.
Say ``client.send_message()`` didn't exist, we could use the `search`__
to look for "message". There we would find `SendMessageRequest`__,
to look for "message". There we would find :tl:`SendMessageRequest`,
which we can work with.
Every request is a Python class, and has the parameters needed for you
@ -45,11 +45,11 @@ If you're going to use a lot of these, you may do:
# We now have access to 'functions.messages.SendMessageRequest'
We see that this request must take at least two parameters, a ``peer``
of type `InputPeer`__, and a ``message`` which is just a Python
of type :tl:`InputPeer`, and a ``message`` which is just a Python
``str``\ ing.
How can we retrieve this ``InputPeer``? We have two options. We manually
`construct one`__, for instance:
How can we retrieve this :tl:`InputPeer`? We have two options. We manually
construct one, for instance:
.. code-block:: python
@ -64,7 +64,7 @@ Or we call ``.get_input_entity()``:
peer = client.get_input_entity('someone')
When you're going to invoke an API method, most require you to pass an
``InputUser``, ``InputChat``, or so on, this is why using
:tl:`InputUser`, :tl:`InputChat`, or so on, this is why using
``.get_input_entity()`` is more straightforward (and often
immediate, if you've seen the user before, know their ID, etc.).
If you also need to have information about the whole user, use
@ -138,6 +138,3 @@ This can further be simplified to:
__ https://lonamiwebs.github.io/Telethon
__ https://lonamiwebs.github.io/Telethon/methods/index.html
__ https://lonamiwebs.github.io/Telethon/?q=message
__ https://lonamiwebs.github.io/Telethon/methods/messages/send_message.html
__ https://lonamiwebs.github.io/Telethon/types/input_peer.html
__ https://lonamiwebs.github.io/Telethon/constructors/input_peer_user.html

View File

@ -9,16 +9,16 @@ Introduction
************
The library widely uses the concept of "entities". An entity will refer
to any ``User``, ``Chat`` or ``Channel`` object that the API may return
in response to certain methods, such as ``GetUsersRequest``.
to any :tl:`User`, :tl:`Chat` or :tl:`Channel` object that the API may return
in response to certain methods, such as :tl:`GetUsersRequest`.
.. note::
When something "entity-like" is required, it means that you need to
provide something that can be turned into an entity. These things include,
but are not limited to, usernames, exact titles, IDs, ``Peer`` objects,
or even entire ``User``, ``Chat`` and ``Channel`` objects and even phone
numbers from people you have in your contacts.
but are not limited to, usernames, exact titles, IDs, :tl:`Peer` objects,
or even entire :tl:`User`, :tl:`Chat` and :tl:`Channel` objects and even
phone numbers from people you have in your contacts.
Getting entities
****************
@ -73,7 +73,7 @@ become possible.
Every entity the library encounters (in any response to any call) will by
default be cached in the ``.session`` file (an SQLite database), to avoid
performing unnecessary API calls. If the entity cannot be found, additonal
calls like ``ResolveUsernameRequest`` or ``GetContactsRequest`` may be
calls like :tl:`ResolveUsernameRequest` or :tl:`GetContactsRequest` may be
made to obtain the required information.
@ -90,14 +90,14 @@ Entities vs. Input Entities
On top of the normal types, the API also make use of what they call their
``Input*`` versions of objects. The input version of an entity (e.g.
``InputPeerUser``, ``InputChat``, etc.) only contains the minimum
:tl:`InputPeerUser`, :tl:`InputChat`, etc.) only contains the minimum
information that's required from Telegram to be able to identify
who you're referring to: a ``Peer``'s **ID** and **hash**.
who you're referring to: a :tl:`Peer`'s **ID** and **hash**.
This ID/hash pair is unique per user, so if you use the pair given by another
user **or bot** it will **not** work.
To save *even more* bandwidth, the API also makes use of the ``Peer``
To save *even more* bandwidth, the API also makes use of the :tl:`Peer`
versions, which just have an ID. This serves to identify them, but
peers alone are not enough to use them. You need to know their hash
before you can "use them".
@ -106,8 +106,8 @@ As we just mentioned, API calls don't need to know the whole information
about the entities, only their ID and hash. For this reason, another method,
``.get_input_entity()`` is available. This will always use the cache while
possible, making zero API calls most of the time. When a request is made,
if you provided the full entity, e.g. an ``User``, the library will convert
it to the required ``InputPeer`` automatically for you.
if you provided the full entity, e.g. an :tl:`User`, the library will convert
it to the required :tl:`InputPeer` automatically for you.
**You should always favour** ``.get_input_entity()`` **over** ``.get_entity()``
for this reason! Calling the latter will always make an API call to get
@ -125,5 +125,5 @@ library, the raw requests you make to the API are also able to call
client(SendMessageRequest('username', 'hello'))
The library will call the ``.resolve()`` method of the request, which will
resolve ``'username'`` with the appropriated ``InputPeer``. Don't worry if
resolve ``'username'`` with the appropriated :tl:`InputPeer`. Don't worry if
you don't get this yet, but remember some of the details here are important.

View File

@ -315,7 +315,7 @@ library alone (when invoking a request), it means that you can now use
``Peer`` types or even usernames where a ``InputPeer`` is required. The
object now has access to the ``client``, so that it can fetch the right
type if needed, or access the session database. Furthermore, you can
reuse requests that need "autocast" (e.g. you put ``User`` but ``InputPeer``
reuse requests that need "autocast" (e.g. you put :tl:`User` but ``InputPeer``
was needed), since ``.resolve()`` is called when invoking. Before, it was
only done on object construction.

View File

@ -91,13 +91,13 @@ class _EventCommon(abc.ABC):
def _get_entity(self, msg_id, entity_id, chat=None):
"""
Helper function to call GetMessages on the give msg_id and
Helper function to call :tl:`GetMessages` on the give msg_id and
return the input entity whose ID is the given entity ID.
If ``chat`` is present it must be an InputPeer.
If ``chat`` is present it must be an :tl:`InputPeer`.
Returns a tuple of (entity, input_peer) if it was found, or
a tuple of (None, None) if it couldn't be.
Returns a tuple of ``(entity, input_peer)`` if it was found, or
a tuple of ``(None, None)`` if it couldn't be.
"""
try:
if isinstance(chat, types.InputPeerChannel):
@ -124,7 +124,7 @@ class _EventCommon(abc.ABC):
@property
def input_chat(self):
"""
The (:obj:`InputPeer`) (group, megagroup or channel) on which
The (:tl:`InputPeer`) (group, megagroup or channel) on which
the event occurred. This doesn't have the title or anything,
but is useful if you don't need those to avoid further
requests.
@ -156,7 +156,7 @@ class _EventCommon(abc.ABC):
@property
def chat(self):
"""
The (:obj:`User` | :obj:`Chat` | :obj:`Channel`, optional) on which
The (:tl:`User` | :tl:`Chat` | :tl:`Channel`, optional) on which
the event occurred. This property may make an API call the first time
to get the most up to date version of the chat (mostly when the event
doesn't belong to a channel), so keep that in mind.
@ -312,8 +312,8 @@ class NewMessage(_EventBuilder):
Represents the event of a new message.
Members:
message (:obj:`Message`):
This is the original ``Message`` object.
message (:tl:`Message`):
This is the original :tl:`Message` object.
is_private (:obj:`bool`):
True if the message was sent as a private message.
@ -406,7 +406,7 @@ class NewMessage(_EventBuilder):
@property
def input_sender(self):
"""
This (:obj:`InputPeer`) is the input version of the user who
This (:tl:`InputPeer`) is the input version of the user who
sent the message. Similarly to ``input_chat``, this doesn't have
things like username or similar, but still useful in some cases.
@ -434,7 +434,7 @@ class NewMessage(_EventBuilder):
@property
def sender(self):
"""
This (:obj:`User`) may make an API call the first time to get
This (:tl:`User`) may make an API call the first time to get
the most up to date version of the sender (mostly when the event
doesn't belong to a channel), so keep that in mind.
@ -474,8 +474,8 @@ class NewMessage(_EventBuilder):
@property
def reply_message(self):
"""
This (:obj:`Message`, optional) will make an API call the first
time to get the full ``Message`` object that one was replying to,
This optional :tl:`Message` will make an API call the first
time to get the full :tl:`Message` object that one was replying to,
so use with care as there is no caching besides local caching yet.
"""
if not self.message.reply_to_msg_id:
@ -498,14 +498,14 @@ class NewMessage(_EventBuilder):
@property
def forward(self):
"""
The unmodified (:obj:`MessageFwdHeader`, optional).
The unmodified :tl:`MessageFwdHeader`, if present..
"""
return self.message.fwd_from
@property
def media(self):
"""
The unmodified (:obj:`MessageMedia`, optional).
The unmodified :tl:`MessageMedia`, if present.
"""
return self.message.media
@ -513,7 +513,7 @@ class NewMessage(_EventBuilder):
def photo(self):
"""
If the message media is a photo,
this returns the (:obj:`Photo`) object.
this returns the :tl:`Photo` object.
"""
if isinstance(self.message.media, types.MessageMediaPhoto):
photo = self.message.media.photo
@ -524,7 +524,7 @@ class NewMessage(_EventBuilder):
def document(self):
"""
If the message media is a document,
this returns the (:obj:`Document`) object.
this returns the :tl:`Document` object.
"""
if isinstance(self.message.media, types.MessageMediaDocument):
doc = self.message.media.document
@ -547,7 +547,7 @@ class NewMessage(_EventBuilder):
def audio(self):
"""
If the message media is a document with an Audio attribute,
this returns the (:obj:`Document`) object.
this returns the :tl:`Document` object.
"""
return self._document_by_attribute(types.DocumentAttributeAudio,
lambda attr: not attr.voice)
@ -556,7 +556,7 @@ class NewMessage(_EventBuilder):
def voice(self):
"""
If the message media is a document with a Voice attribute,
this returns the (:obj:`Document`) object.
this returns the :tl:`Document` object.
"""
return self._document_by_attribute(types.DocumentAttributeAudio,
lambda attr: attr.voice)
@ -565,7 +565,7 @@ class NewMessage(_EventBuilder):
def video(self):
"""
If the message media is a document with a Video attribute,
this returns the (:obj:`Document`) object.
this returns the :tl:`Document` object.
"""
return self._document_by_attribute(types.DocumentAttributeVideo)
@ -573,7 +573,7 @@ class NewMessage(_EventBuilder):
def video_note(self):
"""
If the message media is a document with a Video attribute,
this returns the (:obj:`Document`) object.
this returns the :tl:`Document` object.
"""
return self._document_by_attribute(types.DocumentAttributeVideo,
lambda attr: attr.round_message)
@ -582,7 +582,7 @@ class NewMessage(_EventBuilder):
def gif(self):
"""
If the message media is a document with an Animated attribute,
this returns the (:obj:`Document`) object.
this returns the :tl:`Document` object.
"""
return self._document_by_attribute(types.DocumentAttributeAnimated)
@ -590,7 +590,7 @@ class NewMessage(_EventBuilder):
def sticker(self):
"""
If the message media is a document with a Sticker attribute,
this returns the (:obj:`Document`) object.
this returns the :tl:`Document` object.
"""
return self._document_by_attribute(types.DocumentAttributeSticker)
@ -689,7 +689,7 @@ class ChatAction(_EventBuilder):
new_photo (:obj:`bool`):
``True`` if there's a new chat photo (or it was removed).
photo (:obj:`Photo`, optional):
photo (:tl:`Photo`, optional):
The new photo (or ``None`` if it was removed).
@ -793,7 +793,7 @@ class ChatAction(_EventBuilder):
@property
def pinned_message(self):
"""
If ``new_pin`` is ``True``, this returns the (:obj:`Message`)
If ``new_pin`` is ``True``, this returns the (:tl:`Message`)
object that was pinned.
"""
if self._pinned_message == 0:
@ -857,7 +857,7 @@ class ChatAction(_EventBuilder):
@property
def input_user(self):
"""
Input version of the self.user property.
Input version of the ``self.user`` property.
"""
if self.input_users:
return self._input_users[0]
@ -894,7 +894,7 @@ class ChatAction(_EventBuilder):
@property
def input_users(self):
"""
Input version of the self.users property.
Input version of the ``self.users`` property.
"""
if self._input_users is None and self._user_peers:
self._input_users = []
@ -947,7 +947,7 @@ class UserUpdate(_EventBuilder):
recently (:obj:`bool`):
``True`` if the user was seen within a day.
action (:obj:`SendMessageAction`, optional):
action (:tl:`SendMessageAction`, optional):
The "typing" action if any the user is performing if any.
cancel (:obj:`bool`):

View File

@ -24,13 +24,15 @@ __log__ = logging.getLogger(__name__)
class MtProtoSender:
"""MTProto Mobile Protocol sender
(https://core.telegram.org/mtproto/description).
"""
MTProto Mobile Protocol sender
(https://core.telegram.org/mtproto/description).
Note that this class is not thread-safe, and calling send/receive
from two or more threads at the same time is undefined behaviour.
Rationale: a new connection should be spawned to send/receive requests
in parallel, so thread-safety (hence locking) isn't needed.
Note that this class is not thread-safe, and calling send/receive
from two or more threads at the same time is undefined behaviour.
Rationale:
a new connection should be spawned to send/receive requests
in parallel, so thread-safety (hence locking) isn't needed.
"""
def __init__(self, session, connection):

View File

@ -213,7 +213,7 @@ class TelegramClient(TelegramBareClient):
Whether to force sending as SMS.
Returns:
Information about the result of the request.
An instance of :tl:`SentCode`.
"""
phone = utils.parse_phone(phone) or self._phone
phone_hash = self._phone_code_hash.get(phone)
@ -257,8 +257,9 @@ class TelegramClient(TelegramBareClient):
This is only required if it is enabled in your account.
bot_token (:obj:`str`):
Bot Token obtained by @BotFather to log in as a bot.
Cannot be specified with `phone` (only one of either allowed).
Bot Token obtained by `@BotFather <https://t.me/BotFather>`_
to log in as a bot. Cannot be specified with ``phone`` (only
one of either allowed).
force_sms (:obj:`bool`, optional):
Whether to force sending the code request as SMS.
@ -276,8 +277,8 @@ class TelegramClient(TelegramBareClient):
Similar to the first name, but for the last. Optional.
Returns:
:obj:`TelegramClient`:
This client, so initialization can be chained with `.start()`.
This :obj:`TelegramClient`, so initialization
can be chained with ``.start()``.
"""
if code_callback is None:
@ -453,7 +454,7 @@ class TelegramClient(TelegramBareClient):
Optional last name.
Returns:
The new created user.
The new created :tl:`User`.
"""
if self.is_user_authorized():
self._check_events_pending_resolve()
@ -478,7 +479,7 @@ class TelegramClient(TelegramBareClient):
Logs out Telegram and deletes the current ``*.session`` file.
Returns:
True if the operation was successful.
``True`` if the operation was successful.
"""
try:
self(LogOutRequest())
@ -496,12 +497,12 @@ class TelegramClient(TelegramBareClient):
Args:
input_peer (:obj:`bool`, optional):
Whether to return the ``InputPeerUser`` version or the normal
``User``. This can be useful if you just need to know the ID
Whether to return the :tl:`InputPeerUser` version or the normal
:tl:`User`. This can be useful if you just need to know the ID
of yourself.
Returns:
:obj:`User`: Your own user.
Your own :tl:`User`.
"""
if input_peer and self._self_input_peer:
return self._self_input_peer
@ -541,7 +542,7 @@ class TelegramClient(TelegramBareClient):
offset_id (:obj:`int`, optional):
The message ID to be used as an offset.
offset_peer (:obj:`InputPeer`, optional):
offset_peer (:tl:`InputPeer`, optional):
The peer to be used as an offset.
_total (:obj:`list`, optional):
@ -712,10 +713,10 @@ class TelegramClient(TelegramBareClient):
entity (:obj:`entity`):
To who will it be sent.
message (:obj:`str` | :obj:`Message`):
message (:obj:`str` | :tl:`Message`):
The message to be sent, or another message object to resend.
reply_to (:obj:`int` | :obj:`Message`, optional):
reply_to (:obj:`int` | :tl:`Message`, optional):
Whether to reply to a message or not. If an integer is provided,
it should be the ID of the message that it should reply to.
@ -740,7 +741,7 @@ class TelegramClient(TelegramBareClient):
Has no effect when sending a file.
Returns:
the sent message.
The sent :tl:`Message`.
"""
if file is not None:
return self.send_file(
@ -806,7 +807,7 @@ class TelegramClient(TelegramBareClient):
entity (:obj:`entity`):
To which entity the message(s) will be forwarded.
messages (:obj:`list` | :obj:`int` | :obj:`Message`):
messages (:obj:`list` | :obj:`int` | :tl:`Message`):
The message(s) to forward, or their integer IDs.
from_peer (:obj:`entity`):
@ -815,7 +816,7 @@ class TelegramClient(TelegramBareClient):
order for the forward to work.
Returns:
The forwarded messages.
The list of forwarded :tl:`Message`.
"""
if not utils.is_list_like(messages):
messages = (messages,)
@ -882,7 +883,7 @@ class TelegramClient(TelegramBareClient):
not modified at all.
Returns:
the edited message
The edited :tl:`Message`.
"""
message, msg_entities = self._parse_message_text(message, parse_mode)
request = EditMessageRequest(
@ -905,7 +906,7 @@ class TelegramClient(TelegramBareClient):
be ``None`` for normal chats, but **must** be present
for channels and megagroups.
message_ids (:obj:`list` | :obj:`int` | :obj:`Message`):
message_ids (:obj:`list` | :obj:`int` | :tl:`Message`):
The IDs (or ID) or messages to be deleted.
revoke (:obj:`bool`, optional):
@ -915,7 +916,7 @@ class TelegramClient(TelegramBareClient):
This has no effect on channels or megagroups.
Returns:
The affected messages.
The :tl:`AffectedMessages`.
"""
if not utils.is_list_like(message_ids):
message_ids = (message_ids,)
@ -978,7 +979,7 @@ class TelegramClient(TelegramBareClient):
you are still free to do so.
wait_time (:obj:`int`):
Wait time between different ``GetHistoryRequest``. Use this
Wait time between different :tl:`GetHistoryRequest`. Use this
parameter to avoid hitting the ``FloodWaitError`` as needed.
If left to ``None``, it will default to 1 second only if
the limit is higher than 3000.
@ -987,7 +988,7 @@ class TelegramClient(TelegramBareClient):
A single-item list to pass the total parameter by reference.
Yields:
Instances of ``telethon.tl.types.Message`` with extra attributes:
Instances of :tl:`Message` with extra attributes:
* ``.sender`` = entity of the sender.
* ``.fwd_from.sender`` = if fwd_from, who sent it originally.
@ -995,7 +996,7 @@ class TelegramClient(TelegramBareClient):
* ``.to`` = entity to which the message was sent.
Notes:
Telegram's flood wait limit for ``GetHistoryRequest`` seems to
Telegram's flood wait limit for :tl:`GetHistoryRequest` seems to
be around 30 seconds per 3000 messages, therefore a sleep of 1
second is the default for this limit (or above). You may need
an higher limit, so you're free to set the ``batch_size`` that
@ -1101,7 +1102,7 @@ class TelegramClient(TelegramBareClient):
entity (:obj:`entity`):
The chat where these messages are located.
message (:obj:`list` | :obj:`Message`):
message (:obj:`list` | :tl:`Message`):
Either a list of messages or a single message.
max_id (:obj:`int`):
@ -1172,9 +1173,8 @@ class TelegramClient(TelegramBareClient):
search (:obj:`str`, optional):
Look for participants with this string in name/username.
filter (:obj:`ChannelParticipantsFilter`, optional):
The filter to be used, if you want e.g. only admins. See
https://lonamiwebs.github.io/Telethon/types/channel_participants_filter.html.
filter (:tl:`ChannelParticipantsFilter`, optional):
The filter to be used, if you want e.g. only admins
Note that you might not have permissions for some filter.
This has no effect for normal chats or users.
@ -1192,10 +1192,10 @@ class TelegramClient(TelegramBareClient):
A single-item list to pass the total parameter by reference.
Yields:
The ``User`` objects returned by ``GetParticipantsRequest``
The :tl:`User` objects returned by :tl:`GetParticipantsRequest`
with an additional ``.participant`` attribute which is the
matched ``ChannelParticipant`` type for channels/megagroups
or ``ChatParticipants`` for normal chats.
matched :tl:`ChannelParticipant` type for channels/megagroups
or :tl:`ChatParticipants` for normal chats.
"""
if isinstance(filter, type):
filter = filter()
@ -1362,12 +1362,12 @@ class TelegramClient(TelegramBareClient):
A callback function accepting two parameters:
``(sent bytes, total)``.
reply_to (:obj:`int` | :obj:`Message`):
reply_to (:obj:`int` | :tl:`Message`):
Same as reply_to from .send_message().
attributes (:obj:`list`, optional):
Optional attributes that override the inferred ones, like
``DocumentAttributeFilename`` and so on.
:tl:`DocumentAttributeFilename` and so on.
thumb (:obj:`str` | :obj:`bytes` | :obj:`file`, optional):
Optional thumbnail (for videos).
@ -1390,7 +1390,7 @@ class TelegramClient(TelegramBareClient):
it will be used to determine metadata from audio and video files.
Returns:
The message (or messages) containing the sent file.
The :tl:`Message` (or messages) containing the sent file.
"""
# First check if the user passed an iterable, in which case
# we may want to send as an album if all are photo files.
@ -1551,7 +1551,7 @@ class TelegramClient(TelegramBareClient):
return msg
def send_voice_note(self, *args, **kwargs):
"""Wrapper method around .send_file() with is_voice_note=True"""
"""Wrapper method around :meth:`send_file` with is_voice_note=True."""
kwargs['is_voice_note'] = True
return self.send_file(*args, **kwargs)
@ -1652,8 +1652,8 @@ class TelegramClient(TelegramBareClient):
``(sent bytes, total)``.
Returns:
``InputFileBig`` if the file size is larger than 10MB,
``InputSizedFile`` (subclass of ``InputFile``) otherwise.
:tl:`InputFileBig` if the file size is larger than 10MB,
``InputSizedFile`` (subclass of :tl:`InputFile`) otherwise.
"""
if isinstance(file, (InputFile, InputFileBig)):
return file # Already uploaded
@ -1836,7 +1836,7 @@ class TelegramClient(TelegramBareClient):
"""
Downloads the given media, or the media from a specified Message.
message (:obj:`Message` | :obj:`Media`):
message (:tl:`Message` | :tl:`Media`):
The media or message containing the media that will be downloaded.
file (:obj:`str` | :obj:`file`, optional):
@ -1845,7 +1845,7 @@ class TelegramClient(TelegramBareClient):
progress_callback (:obj:`callable`, optional):
A callback function accepting two parameters:
``(recv bytes, total)``.
``(received bytes, total)``.
Returns:
``None`` if no media was provided, or if it was Empty. On success
@ -2065,7 +2065,7 @@ class TelegramClient(TelegramBareClient):
Downloads the given input location to a file.
Args:
input_location (:obj:`InputFileLocation`):
input_location (:tl:`InputFileLocation`):
The file location from which the file will be downloaded.
file (:obj:`str` | :obj:`file`):
@ -2293,7 +2293,7 @@ class TelegramClient(TelegramBareClient):
"""
Turns the given entity into a valid Telegram user or chat.
entity (:obj:`str` | :obj:`int` | :obj:`Peer` | :obj:`InputPeer`):
entity (:obj:`str` | :obj:`int` | :tl:`Peer` | :tl:`InputPeer`):
The entity (or iterable of entities) to be transformed.
If it's a string which can be converted to an integer or starts
with '+' it will be resolved as if it were a phone number.
@ -2309,7 +2309,7 @@ class TelegramClient(TelegramBareClient):
error will be raised.
Returns:
``User``, ``Chat`` or ``Channel`` corresponding to the input
:tl:`User`, :tl:`Chat` or :tl:`Channel` corresponding to the input
entity.
"""
if utils.is_list_like(entity):
@ -2410,9 +2410,9 @@ class TelegramClient(TelegramBareClient):
use this kind of InputUser, InputChat and so on, so this is the
most suitable call to make for those cases.
entity (:obj:`str` | :obj:`int` | :obj:`Peer` | :obj:`InputPeer`):
entity (:obj:`str` | :obj:`int` | :tl:`Peer` | :tl:`InputPeer`):
The integer ID of an user or otherwise either of a
``PeerUser``, ``PeerChat`` or ``PeerChannel``, for
:tl:`PeerUser`, :tl:`PeerChat` or :tl:`PeerChannel`, for
which to get its ``Input*`` version.
If this ``Peer`` hasn't been seen before by the library, the top
@ -2423,7 +2423,7 @@ class TelegramClient(TelegramBareClient):
a ValueError will be raised.
Returns:
``InputPeerUser``, ``InputPeerChat`` or ``InputPeerChannel``.
:tl:`InputPeerUser`, :tl:`InputPeerChat` or :tl:`InputPeerChannel`.
"""
try:
# First try to get the entity from cache, otherwise figure it out

View File

@ -10,13 +10,13 @@ class Dialog:
return instances of this class when calling :meth:`.get_dialogs()`.
Args:
dialog (:obj:`Dialog`):
dialog (:tl:`Dialog`):
The original ``Dialog`` instance.
pinned (:obj:`bool`):
Whether this dialog is pinned to the top or not.
message (:obj:`Message`):
message (:tl:`Message`):
The last message sent on this dialog. Note that this member
will not be updated when new messages arrive, it's only set
on creation of the instance.
@ -27,7 +27,7 @@ class Dialog:
entity (:obj:`entity`):
The entity that belongs to this dialog (user, chat or channel).
input_entity (:obj:`InputPeer`):
input_entity (:tl:`InputPeer`):
Input version of the entity.
id (:obj:`int`):

View File

@ -128,7 +128,7 @@ class Draft:
def send(self, clear=True, parse_mode='md'):
"""
Sends the contents of this draft to the dialog. This is just a
wrapper around send_message(dialog.input_entity, *args, **kwargs).
wrapper around ``send_message(dialog.input_entity, *args, **kwargs)``.
"""
self._client.send_message(self._peer, self.text,
reply_to=self.reply_to_msg_id,

View File

@ -11,8 +11,9 @@ __log__ = logging.getLogger(__name__)
class UpdateState:
"""Used to hold the current state of processed updates.
To retrieve an update, .poll() should be called.
"""
Used to hold the current state of processed updates.
To retrieve an update, :meth:`poll` should be called.
"""
WORKER_POLL_TIMEOUT = 5.0 # Avoid waiting forever on the workers

View File

@ -38,8 +38,8 @@ VALID_USERNAME_RE = re.compile(r'^[a-zA-Z][\w\d]{3,30}[a-zA-Z\d]$')
def get_display_name(entity):
"""
Gets the display name for the given entity, if it's an ``User``,
``Chat`` or ``Channel``. Returns an empty string otherwise.
Gets the display name for the given entity, if it's an :tl:`User`,
:tl:`Chat` or :tl:`Channel`. Returns an empty string otherwise.
"""
if isinstance(entity, User):
if entity.last_name and entity.first_name:
@ -58,7 +58,7 @@ def get_display_name(entity):
def get_extension(media):
"""Gets the corresponding extension for any Telegram media"""
"""Gets the corresponding extension for any Telegram media."""
# Photos are always compressed as .jpg by Telegram
if isinstance(media, (UserProfilePhoto, ChatPhoto, MessageMediaPhoto)):
@ -83,8 +83,10 @@ 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."""
"""
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.
"""
try:
if entity.SUBCLASS_OF_ID == 0xc91c90b6: # crc32(b'InputPeer')
return entity
@ -129,7 +131,7 @@ def get_input_peer(entity, allow_self=True):
def get_input_channel(entity):
"""Similar to get_input_peer, but for InputChannel's alone"""
"""Similar to :meth:`get_input_peer`, but for :tl:`InputChannel`'s alone."""
try:
if entity.SUBCLASS_OF_ID == 0x40f202fd: # crc32(b'InputChannel')
return entity
@ -146,7 +148,7 @@ def get_input_channel(entity):
def get_input_user(entity):
"""Similar to get_input_peer, but for InputUser's alone"""
"""Similar to :meth:`get_input_peer`, but for :tl:`InputUser`'s alone."""
try:
if entity.SUBCLASS_OF_ID == 0xe669bf46: # crc32(b'InputUser'):
return entity
@ -175,7 +177,7 @@ def get_input_user(entity):
def get_input_document(document):
"""Similar to get_input_peer, but for documents"""
"""Similar to :meth:`get_input_peer`, but for documents"""
try:
if document.SUBCLASS_OF_ID == 0xf33fdb68: # crc32(b'InputDocument'):
return document
@ -198,7 +200,7 @@ def get_input_document(document):
def get_input_photo(photo):
"""Similar to get_input_peer, but for documents"""
"""Similar to :meth:`get_input_peer`, but for photos"""
try:
if photo.SUBCLASS_OF_ID == 0x846363e0: # crc32(b'InputPhoto'):
return photo
@ -218,7 +220,7 @@ def get_input_photo(photo):
def get_input_geo(geo):
"""Similar to get_input_peer, but for geo points"""
"""Similar to :meth:`get_input_peer`, but for geo points"""
try:
if geo.SUBCLASS_OF_ID == 0x430d225: # crc32(b'InputGeoPoint'):
return geo
@ -241,10 +243,11 @@ def get_input_geo(geo):
def get_input_media(media, is_photo=False):
"""Similar to get_input_peer, but for media.
"""
Similar to :meth:`get_input_peer`, but for media.
If the media is a file location and is_photo is known to be True,
it will be treated as an InputMediaUploadedPhoto.
If the media is a file location and ``is_photo`` is known to be ``True``,
it will be treated as an :tl:`InputMediaUploadedPhoto`.
"""
try:
if media.SUBCLASS_OF_ID == 0xfaf846f4: # crc32(b'InputMedia'):
@ -317,7 +320,7 @@ def get_input_media(media, is_photo=False):
def is_image(file):
"""
Returns True if the file extension looks like an image file to Telegram.
Returns ``True`` if the file extension looks like an image file to Telegram.
"""
if not isinstance(file, str):
return False
@ -326,23 +329,23 @@ def is_image(file):
def is_audio(file):
"""Returns True if the file extension looks like an audio file"""
"""Returns ``True`` if the file extension looks like an audio file."""
return (isinstance(file, str) and
(mimetypes.guess_type(file)[0] or '').startswith('audio/'))
def is_video(file):
"""Returns True if the file extension looks like a video file"""
"""Returns ``True`` if the file extension looks like a video file."""
return (isinstance(file, str) and
(mimetypes.guess_type(file)[0] or '').startswith('video/'))
def is_list_like(obj):
"""
Returns True if the given object looks like a list.
Returns ``True`` if the given object looks like a list.
Checking if hasattr(obj, '__iter__') and ignoring str/bytes is not
enough. Things like open() are also iterable (and probably many
Checking ``if hasattr(obj, '__iter__')`` and ignoring ``str/bytes`` is not
enough. Things like ``open()`` are also iterable (and probably many
other things), so just support the commonly known list-like objects.
"""
return isinstance(obj, (list, tuple, set, dict,
@ -350,7 +353,7 @@ def is_list_like(obj):
def parse_phone(phone):
"""Parses the given phone, or returns None if it's invalid"""
"""Parses the given phone, or returns ``None`` if it's invalid."""
if isinstance(phone, int):
return str(phone)
else:
@ -365,7 +368,7 @@ def parse_username(username):
both the stripped, lowercase username and whether it is
a joinchat/ hash (in which case is not lowercase'd).
Returns None if the username is not valid.
Returns ``None`` if the ``username`` is not valid.
"""
username = username.strip()
m = USERNAME_RE.match(username)
@ -386,7 +389,7 @@ def parse_username(username):
def _fix_peer_id(peer_id):
"""
Fixes the peer ID for chats and channels, in case the users
mix marking the ID with the ``Peer()`` constructors.
mix marking the ID with the :tl:`Peer` constructors.
"""
peer_id = abs(peer_id)
if str(peer_id).startswith('100'):
@ -401,7 +404,7 @@ def get_peer_id(peer):
chat ID is negated, and channel ID is prefixed with -100.
The original ID and the peer type class can be returned with
a call to utils.resolve_id(marked_id).
a call to :meth:`resolve_id(marked_id)`.
"""
# First we assert it's a Peer TLObject, or early return for integers
if isinstance(peer, int):
@ -450,7 +453,7 @@ def get_peer_id(peer):
def resolve_id(marked_id):
"""Given a marked ID, returns the original ID and its Peer type"""
"""Given a marked ID, returns the original ID and its :tl:`Peer` type."""
if marked_id >= 0:
return marked_id, PeerUser
@ -461,8 +464,10 @@ def resolve_id(marked_id):
def get_appropriated_part_size(file_size):
"""Gets the appropriated part size when uploading or downloading files,
given an initial file size"""
"""
Gets the appropriated part size when uploading or downloading files,
given an initial file size.
"""
if file_size <= 104857600: # 100MB
return 128
if file_size <= 786432000: # 750MB