From be3ed894c6a157404204683bcda630eab5584c25 Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Fri, 17 Sep 2021 20:04:57 +0200 Subject: [PATCH] Make changes to the default limit in client.get_list methods --- readthedocs/misc/v2-migration-guide.rst | 25 +++++++++++++++++++++++++ telethon/_client/dialogs.py | 10 ++++++---- telethon/_client/telegramclient.py | 10 +++++----- telethon/_misc/requestiter.py | 16 +++++++++++++--- 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/readthedocs/misc/v2-migration-guide.rst b/readthedocs/misc/v2-migration-guide.rst index e48fb41a..cf5fce04 100644 --- a/readthedocs/misc/v2-migration-guide.rst +++ b/readthedocs/misc/v2-migration-guide.rst @@ -80,6 +80,31 @@ The removed methods are: The only exception to this rule is ``iter_download``. +Additionally, when using ``await``, if the method was called with a limit of 1 (either through +setting just one value to fetch, or setting the limit to one), either ``None`` or a single item +(outside of a ``list``) will be returned. This used to be the case only for ``get_messages``, +but now all methods behave in the same way for consistency. + +When using ``async for``, the default limit will be ``None``, meaning all items will be fetched. +When using ``await``, the default limit will be ``1``, meaning the latest item will be fetched. +If you want to use ``await`` but still get a list, use the ``.collect()`` method to collect the +results into a list: + +.. code-block:: python + + chat = ... + + # will iterate over all (default limit=None) + async for message in client.get_messages(chat): + ... + + # will return either a single Message or None if there is not any (limit=1) + message = await client.get_messages(chat) + + # will collect all messages into a list (default limit=None). will also take long! + all_messages = await client.get_messages(chat).collect() + + // TODO keep providing the old ``iter_`` versions? it doesn't really hurt, even if the recommended way changed // TODO does the download really need to be special? get download is kind of weird though diff --git a/telethon/_client/dialogs.py b/telethon/_client/dialogs.py index d4b4644b..1277a3a4 100644 --- a/telethon/_client/dialogs.py +++ b/telethon/_client/dialogs.py @@ -167,11 +167,13 @@ def get_drafts( self: 'TelegramClient', entity: 'hints.EntitiesLike' = None ) -> _DraftsIter: - if entity and not utils.is_list_like(entity): - entity = (entity,) + limit = None + if entity: + if not utils.is_list_like(entity): + entity = (entity,) + limit = len(entity) - # TODO Passing a limit here makes no sense - return _DraftsIter(self, None, entities=entity) + return _DraftsIter(self, limit, entities=entity) async def edit_folder( diff --git a/telethon/_client/telegramclient.py b/telethon/_client/telegramclient.py index 1482dbdd..1501fee3 100644 --- a/telethon/_client/telegramclient.py +++ b/telethon/_client/telegramclient.py @@ -719,7 +719,7 @@ class TelegramClient: def get_participants( self: 'TelegramClient', entity: 'hints.EntityLike', - limit: float = None, + limit: float = (), *, search: str = '', filter: '_tl.TypeChannelParticipantsFilter' = None, @@ -794,7 +794,7 @@ class TelegramClient: def get_admin_log( self: 'TelegramClient', entity: 'hints.EntityLike', - limit: float = None, + limit: float = (), *, max_id: int = 0, min_id: int = 0, @@ -925,7 +925,7 @@ class TelegramClient: def get_profile_photos( self: 'TelegramClient', entity: 'hints.EntityLike', - limit: int = None, + limit: int = (), *, offset: int = 0, max_id: int = 0) -> chats._ProfilePhotoIter: @@ -1396,7 +1396,7 @@ class TelegramClient: def get_dialogs( self: 'TelegramClient', - limit: float = None, + limit: float = (), *, offset_date: 'hints.DateLike' = None, offset_id: int = 0, @@ -1963,7 +1963,7 @@ class TelegramClient: def get_messages( self: 'TelegramClient', entity: 'hints.EntityLike', - limit: float = None, + limit: float = (), *, offset_date: 'hints.DateLike' = None, offset_id: int = 0, diff --git a/telethon/_misc/requestiter.py b/telethon/_misc/requestiter.py index 9c837c05..96ceb97a 100644 --- a/telethon/_misc/requestiter.py +++ b/telethon/_misc/requestiter.py @@ -28,12 +28,13 @@ class RequestIter(abc.ABC): self.reverse = reverse self.wait_time = wait_time self.kwargs = kwargs - self.limit = max(float('inf') if limit is None else limit, 0) + self.limit = max(float('inf') if limit is None or limit == () else limit, 0) self.left = self.limit self.buffer = None self.index = 0 self.total = None self.last_load = 0 + self.return_single = limit == 1 or limit == () async def _init(self, **kwargs): """ @@ -86,11 +87,20 @@ class RequestIter(abc.ABC): self.left = self.limit return self - async def collect(self): + async def collect(self, force_list=True): """ Create a `self` iterator and collect it into a `TotalList` (a normal list with a `.total` attribute). + + If ``force_list`` is ``False`` and ``self.return_single`` is ``True``, no list + will be returned. Instead, either a single item or ``None`` will be returned. """ + if not force_list and self.return_single: + self.limit = 1 + async for message in self: + return message + return None + result = helpers.TotalList() async for message in self: result.append(message) @@ -116,4 +126,4 @@ class RequestIter(abc.ABC): return self # __aiter__ will be called after, too def __await__(self): - return self.collect().__await__() + return self.collect(force_list=False).__await__()