From f8e428bd5b01fb86032d727a7e8b10e3048b5fcf Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 4 Dec 2020 09:32:53 +1000 Subject: [PATCH] Add support for chunking AsyncIterator objects --- discord/iterators.py | 25 +++++++++++++++++++++++++ docs/api.rst | 20 ++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/discord/iterators.py b/discord/iterators.py index 34dcd4126..514316511 100644 --- a/discord/iterators.py +++ b/discord/iterators.py @@ -62,6 +62,11 @@ class _AsyncIterator: if ret: return elem + def chunk(self, max_size): + if max_size <= 0: + raise ValueError('async iterator chunk sizes must be greater than 0.') + return _ChunkedAsyncIterator(self, max_size) + def map(self, func): return _MappedAsyncIterator(self, func) @@ -92,6 +97,26 @@ class _AsyncIterator: def _identity(x): return x +class _ChunkedAsyncIterator(_AsyncIterator): + def __init__(self, iterator, max_size): + self.iterator = iterator + self.max_size = max_size + + async def next(self): + ret = [] + n = 0 + while n < self.max_size: + try: + item = await self.iterator.next() + except NoMoreItems: + if ret: + return ret + raise + else: + ret.append(item) + n += 1 + return ret + class _MappedAsyncIterator(_AsyncIterator): def __init__(self, iterator, func): self.iterator = iterator diff --git a/docs/api.rst b/docs/api.rst index 6790f3959..892e175ef 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -2085,6 +2085,26 @@ Certain utilities make working with async iterators easier, detailed below. :return: A list of every element in the async iterator. :rtype: list + .. method:: chunk(max_size) + + Collects items into chunks of up to a given maximum size. + Another :class:`AsyncIterator` is returned which collects items into + :class:`list`\s of a given size. The maximum chunk size must be a positive integer. + + .. versionadded:: 1.6 + + Collecting groups of users: :: + + async for leader, *users in reaction.users().chunk(3): + ... + + .. warning:: + + The last chunk collected may not be as large as ``max_size``. + + :param max_size: The size of individual chunks. + :rtype: :class:`AsyncIterator` + .. method:: map(func) This is similar to the built-in :func:`map ` function. Another