Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-aioitertools for
openSUSE:Factory checked in at 2021-08-28 22:29:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-aioitertools (Old)
and /work/SRC/openSUSE:Factory/.python-aioitertools.new.1899 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-aioitertools"
Sat Aug 28 22:29:23 2021 rev:3 rq:914749 version:0.8.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-aioitertools/python-aioitertools.changes
2021-05-13 22:18:59.163495261 +0200
+++
/work/SRC/openSUSE:Factory/.python-aioitertools.new.1899/python-aioitertools.changes
2021-08-28 22:29:49.402018971 +0200
@@ -1,0 +2,13 @@
+Tue Aug 17 10:11:54 UTC 2021 - John Paul Adrian Glaubitz
<[email protected]>
+
+- Update to 0.8.0:
+ - Added `builtins.any()` and `builtins.all()` (#44)
+ - `builtins.next()` takes an optional `default` parameter (#40, #41)
+ - `asyncio.gather()` now handles cancellation (#64)
+ - Better exception handling in `itertools.tee()` (#47)
+ - Removed dependency on typing_extensions for Python 3.8 and newer (#49)
+ - Improved documentation and formatting
+- Drop patches for issues fixed upstream
+ - stdlib-typing_extensions.patch
+
+-------------------------------------------------------------------
Old:
----
aioitertools-0.7.1.tar.gz
stdlib-typing_extensions.patch
New:
----
aioitertools-0.8.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-aioitertools.spec ++++++
--- /var/tmp/diff_new_pack.Gs9G80/_old 2021-08-28 22:29:49.902019527 +0200
+++ /var/tmp/diff_new_pack.Gs9G80/_new 2021-08-28 22:29:49.906019531 +0200
@@ -19,16 +19,13 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%define skip_python2 1
Name: python-aioitertools
-Version: 0.7.1
+Version: 0.8.0
Release: 0
Summary: itertools and builtins for AsyncIO and mixed iterables
License: MIT
Group: Development/Languages/Python
URL: https://aioitertools.omnilib.dev
Source:
https://files.pythonhosted.org/packages/source/a/aioitertools/aioitertools-%{version}.tar.gz
-# PATCH-FIX-UPSTREAM stdlib-typing_extensions.patch gh#omnilib/aioitertools#49
[email protected]
-# Improve dependencies for Python 3.8+
-Patch0: stdlib-typing_extensions.patch
BuildRequires: %{python_module asyncio}
BuildRequires: %{python_module setuptools}
BuildRequires: %{python_module typing_extensions if %python-base < 3.8}
++++++ aioitertools-0.7.1.tar.gz -> aioitertools-0.8.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/.flake8
new/aioitertools-0.8.0/.flake8
--- old/aioitertools-0.7.1/.flake8 1970-01-01 01:00:00.000000000 +0100
+++ new/aioitertools-0.8.0/.flake8 2021-05-16 22:57:53.159477500 +0200
@@ -0,0 +1,13 @@
+[flake8]
+ignore =
+ # mccabe complexity
+ C901
+
+ # covered by black/usort
+ E1
+ E2
+ E3
+ E4
+max-line-length = 88
+per-file-ignores =
+ __init__.py: F401
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/CHANGELOG.md
new/aioitertools-0.8.0/CHANGELOG.md
--- old/aioitertools-0.7.1/CHANGELOG.md 2020-11-09 04:56:44.066201000 +0100
+++ new/aioitertools-0.8.0/CHANGELOG.md 2021-08-05 04:24:00.792124300 +0200
@@ -1,6 +1,31 @@
aioitertools
============
+v0.8.0
+------
+
+Feature release:
+
+- Added `builtins.any()` and `builtins.all()` (#44)
+- `builtins.next()` takes an optional `default` parameter (#40, #41)
+- `asyncio.gather()` now handles cancellation (#64)
+- Better exception handling in `itertools.tee()` (#47)
+- Removed dependency on typing_extensions for Python 3.8 and newer (#49)
+- Improved documentation and formatting
+
+```
+$ git shortlog -s v0.7.1...v0.8.0
+ 1 Bryan Forbes
+ 2 Jason Fried
+ 15 John Reese
+ 1 Kevin Stone
+ 3 Roger Aiudi
+ 3 Sunyeop Lee
+ 1 Yop
+ 10 pyup.io bot
+```
+
+
v0.7.1
------
@@ -176,7 +201,7 @@
- Unit tests for all builtins
```
-$ git shortlog -s ce32bdb1777f84e8f64b9470d81b84b754389dd9...v0.1.0
- 1 John Reese
+$ git shortlog -s v0.1.0
+ 2 John Reese
```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/PKG-INFO
new/aioitertools-0.8.0/PKG-INFO
--- old/aioitertools-0.7.1/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
+++ new/aioitertools-0.8.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
@@ -1,7 +1,109 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
Name: aioitertools
-Version: 0.7.1
+Version: 0.8.0
Summary: itertools and builtins for AsyncIO and mixed iterables
Home-page: https://aioitertools.omnilib.dev
Author: John Reese
Author-email: [email protected]
+Requires-Python: >=3.6
+Description-Content-Type: text/markdown
+Classifier: Development Status :: 4 - Beta
+Classifier: Framework :: AsyncIO
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Topic :: Software Development :: Libraries
+Requires-Dist: typing_extensions>=3.7; python_version < '3.8'
+Project-URL: Documentation, https://aioitertools.omnilib.dev/en/latest/
+Project-URL: Github, https://github.com/omnilib/aioitertools
+
+aioitertools
+============
+
+Implementation of itertools, builtins, and more for AsyncIO and mixed-type
iterables.
+
+[](https://github.com/omnilib/aioitertools/actions)
+[](https://codecov.io/gh/omnilib/aioitertools)
+[](https://pypi.org/project/aioitertools)
+[](https://github.com/omnilib/aioitertools/blob/master/LICENSE)
+[](https://github.com/ambv/black)
+
+
+Install
+-------
+
+aioitertools requires Python 3.6 or newer.
+You can install it from PyPI:
+
+ $ pip install aioitertools
+
+
+Usage
+-----
+
+aioitertools shadows the standard library whenever possible to provide
+asynchronous version of the modules and functions you already know. It's
+fully compatible with standard iterators and async iterators alike, giving
+you one unified,??familiar interface for interacting with iterable objects:
+
+```python
+from aioitertools import iter, next, map, zip
+
+something = iter(...)
+first_item = await next(something)
+
+async for item in iter(something):
+ ...
+
+
+async def fetch(url):
+ response = await aiohttp.request(...)
+ return response.json
+
+async for value in map(fetch, MANY_URLS):
+ ...
+
+
+async for a, b in zip(something, something_else):
+ ...
+```
+
+
+aioitertools emulates the entire `itertools` module, offering the same
+function signatures, but as async generators. All functions support
+standard iterables and async iterables alike, and can take functions or
+coroutines:
+
+```python
+from aioitertools import chain, islice
+
+async def generator1(...):
+ yield ...
+
+async def generator2(...):
+ yield ...
+
+async for value in chain(generator1(), generator2()):
+ ...
+
+async for value in islice(generator1(), 2, None, 2):
+ ...
+```
+
+
+See [builtins.py][], [itertools.py][], and [more_itertools.py][] for full
+documentation of functions and abilities.
+
+
+License
+-------
+
+aioitertools is copyright [John Reese](https://jreese.sh), and licensed under
+the MIT license. I am providing code in this repository to you under an open
+source license. This is my personal repository; the license you receive to
+my code is from me and not from my employer. See the `LICENSE` file for
details.
+
+
+[builtins.py]:
https://github.com/omnilib/aioitertools/blob/master/aioitertools/builtins.py
+[itertools.py]:
https://github.com/omnilib/aioitertools/blob/master/aioitertools/itertools.py
+[more_itertools.py]:
https://github.com/omnilib/aioitertools/blob/master/aioitertools/more_itertools.py
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/aioitertools/__init__.py
new/aioitertools-0.8.0/aioitertools/__init__.py
--- old/aioitertools-0.7.1/aioitertools/__init__.py 2020-11-09
04:47:28.899267000 +0100
+++ new/aioitertools-0.8.0/aioitertools/__init__.py 2021-08-05
04:22:56.171010700 +0200
@@ -8,7 +8,20 @@
__author__ = "John Reese"
from . import asyncio
from .__version__ import __version__
-from .builtins import enumerate, iter, list, map, max, min, next, set, sum, zip
+from .builtins import (
+ all,
+ any,
+ enumerate,
+ iter,
+ list,
+ map,
+ max,
+ min,
+ next,
+ set,
+ sum,
+ zip,
+)
from .itertools import (
accumulate,
chain,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/aioitertools/__version__.py
new/aioitertools-0.8.0/aioitertools/__version__.py
--- old/aioitertools-0.7.1/aioitertools/__version__.py 2020-11-09
04:56:44.081393200 +0100
+++ new/aioitertools-0.8.0/aioitertools/__version__.py 2021-08-05
04:24:00.800830100 +0200
@@ -1 +1 @@
-__version__ = "0.7.1"
+__version__ = "0.8.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/aioitertools/asyncio.py
new/aioitertools-0.8.0/aioitertools/asyncio.py
--- old/aioitertools-0.7.1/aioitertools/asyncio.py 2020-11-09
04:47:28.889947000 +0100
+++ new/aioitertools-0.8.0/aioitertools/asyncio.py 2021-08-05
04:22:56.166504100 +0200
@@ -11,7 +11,8 @@
import time
from typing import Any, Awaitable, Dict, Iterable, List, Optional, Set, Tuple,
cast
-from .types import AsyncIterator, T
+from .builtins import maybe_await, iter as aiter
+from .types import AsyncIterator, MaybeAwaitable, AnyIterable, T
async def as_completed(
@@ -26,7 +27,7 @@
Unlike `asyncio.as_completed`, this yields actual results, and does not
require
awaiting each item in the iterable.
- Example:
+ Example::
async for value in as_completed(futures):
... # use value immediately
@@ -52,8 +53,8 @@
# returns Tuple[Set[Future], Set[Future]. Because mypy doesn't like
assigning
# these values to existing Set[Awaitable] or even Set[Union[Awaitable,
Future]],
# we need to first cast the results to something that we can actually
use
- # asyncio.Future:
https://github.com/python/typeshed/blob/72ff7b94e534c610ddf8939bacbc55343e9465d2/stdlib/3/asyncio/futures.pyi#L30
- # asyncio.wait():
https://github.com/python/typeshed/blob/72ff7b94e534c610ddf8939bacbc55343e9465d2/stdlib/3/asyncio/tasks.pyi#L89
+ # asyncio.Future:
https://github.com/python/typeshed/blob/72ff7b94e534c610ddf8939bacbc55343e9465d2/stdlib/3/asyncio/futures.pyi#L30
# noqa: E501
+ # asyncio.wait():
https://github.com/python/typeshed/blob/72ff7b94e534c610ddf8939bacbc55343e9465d2/stdlib/3/asyncio/tasks.pyi#L89
# noqa: E501
done, pending = cast(
Tuple[Set[Awaitable[T]], Set[Awaitable[T]]],
await asyncio.wait(
@@ -74,10 +75,19 @@
return_exceptions: bool = False,
limit: int = -1
) -> List[Any]:
- """Like asyncio.gather but with a limit on concurrency.
+ """
+ Like asyncio.gather but with a limit on concurrency.
+
+ Note that all results are buffered.
+
+ If gather is cancelled all tasks that were internally created and still
pending
+ will be cancelled as well.
- Much of the complexity of gather comes with it support for cancel, which we
- omit here. Note that all results are buffered.
+ Example::
+
+ futures = [some_coro(i) for i in range(10)]
+
+ results = await gather(*futures, limit=2)
"""
# For detecting input duplicates and reconciling them at the end
@@ -112,14 +122,22 @@
# pending might be empty if the last items of args were dupes;
# asyncio.wait([]) will raise an exception.
if pending:
- done, pending = await asyncio.wait(
- pending, loop=loop, return_when=asyncio.FIRST_COMPLETED
- )
- for x in done:
- if return_exceptions and x.exception():
- ret[pos[x]] = x.exception()
- else:
- ret[pos[x]] = x.result()
+ try:
+ done, pending = await asyncio.wait(
+ pending, loop=loop, return_when=asyncio.FIRST_COMPLETED
+ )
+ for x in done:
+ if return_exceptions and x.exception():
+ ret[pos[x]] = x.exception()
+ else:
+ ret[pos[x]] = x.result()
+ except asyncio.CancelledError:
+ # Since we created these tasks we should cancel them
+ for x in pending:
+ x.cancel()
+ # we insure that all tasks are cancelled before we raise
+ await asyncio.gather(*pending, loop=loop,
return_exceptions=True)
+ raise
if not pending and next_arg == len(args):
break
@@ -129,3 +147,22 @@
ret[lst[i]] = ret[lst[0]]
return ret
+
+
+async def gather_iter(
+ itr: AnyIterable[MaybeAwaitable[T]],
+ loop: Optional[asyncio.AbstractEventLoop] = None,
+ return_exceptions: bool = False,
+ limit: int = -1,
+) -> List[T]:
+ """
+ Wrapper around gather to handle gathering an iterable instead of *args.
+
+ Note that the iterable values don't have to be awaitable.
+ """
+ return await gather(
+ *[maybe_await(i) async for i in aiter(itr)],
+ loop=loop,
+ return_exceptions=return_exceptions,
+ limit=limit,
+ )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/aioitertools/builtins.py
new/aioitertools-0.8.0/aioitertools/builtins.py
--- old/aioitertools-0.7.1/aioitertools/builtins.py 2020-11-09
04:47:28.821214700 +0100
+++ new/aioitertools-0.8.0/aioitertools/builtins.py 2021-08-05
04:22:57.200909100 +0200
@@ -13,6 +13,7 @@
import asyncio
import builtins
+from enum import Enum
from typing import (
Any,
AsyncIterable,
@@ -28,8 +29,59 @@
overload,
)
+from . import asyncio as ait_asyncio
from .helpers import Orderable, maybe_await
-from .types import T1, T2, T3, T4, T5, AnyIterable, AnyIterator, AnyStop, R, T
+from .types import (
+ T1,
+ T2,
+ T3,
+ T4,
+ T5,
+ AnyIterable,
+ AnyIterator,
+ AnyStop,
+ R,
+ T,
+ MaybeAwaitable,
+)
+
+
+class Sentinel(Enum):
+ """
+ :meta private:
+ """
+
+ MISSING = object()
+
+
+async def all(itr: AnyIterable[MaybeAwaitable[Any]]) -> bool:
+ """
+ Return True if all values are truthy in a mixed iterable, else False.
+ The iterable will be fully consumed and any awaitables will
+ automatically be awaited.
+
+ Example::
+
+ if await all(it):
+ ...
+
+ """
+ return builtins.all(await ait_asyncio.gather_iter(itr))
+
+
+async def any(itr: AnyIterable[MaybeAwaitable[Any]]) -> bool:
+ """
+ Return True if any value is truthy in a mixed iterable, else False.
+ The iterable will be fully consumed and any awaitables will
+ automatically be awaited.
+
+ Example::
+
+ if await any(it):
+ ...
+
+ """
+ return builtins.any(await ait_asyncio.gather_iter(itr))
def iter(itr: AnyIterable[T]) -> AsyncIterator[T]:
@@ -41,9 +93,9 @@
Standard iterables will be wrapped in an async generator yielding
each item in the iterable in the same order.
- Examples:
+ Examples::
- async for iter(range(10)):
+ async for value in iter(range(10)):
...
"""
@@ -60,32 +112,49 @@
return gen()
+@overload
async def next(itr: AnyIterator[T]) -> T:
+ ...
+
+
+@overload
+async def next(itr: AnyIterator[T1], default: T2) -> Union[T1, T2]:
+ ...
+
+
+async def next(
+ itr: AnyIterator[T1], default: Union[T2, Sentinel] = Sentinel.MISSING
+) -> Union[T1, T2]:
"""
Return the next item of any mixed iterator.
Calls builtins.next() on standard iterators, and awaits itr.__anext__()
on async iterators.
- Example:
+ Example::
value = await next(it)
"""
- if isinstance(itr, AsyncIterator):
- return await itr.__anext__()
-
try:
- return builtins.next(itr)
- except StopIteration:
- raise StopAsyncIteration
+ if isinstance(itr, AsyncIterator):
+ return await itr.__anext__()
+
+ try:
+ return builtins.next(itr)
+ except StopIteration:
+ raise StopAsyncIteration
+ except StopAsyncIteration:
+ if default is Sentinel.MISSING:
+ raise
+ return default
async def list(itr: AnyIterable[T]) -> List[T]:
"""
Consume a mixed iterable and return a list of items in order.
- Example:
+ Example::
await list(range(5))
-> [0, 1, 2, 3, 4]
@@ -98,7 +167,7 @@
"""
Consume a mixed iterable and return a set of items.
- Example:
+ Example::
await set([0, 1, 2, 3, 0, 1, 2, 3])
-> {0, 1, 2, 3}
@@ -113,7 +182,7 @@
"""
Consume a mixed iterable and yield the current index and item.
- Example:
+ Example::
async for index, value in enumerate(...):
...
@@ -129,7 +198,7 @@
"""
Modify item of a mixed iterable using the given function or coroutine.
- Example:
+ Example::
async for response in map(func, data):
...
@@ -158,7 +227,7 @@
"""
Return the largest item in an iterable or the largest of two or more
arguments.
- Example:
+ Example::
await min(range(5))
-> 4
@@ -217,7 +286,7 @@
"""
Return the smallest item in an iterable or the smallest of two or more
arguments.
- Example:
+ Example::
await min(range(5))
-> 0
@@ -262,7 +331,7 @@
"""
Compute the sum of a mixed iterable, adding each value with the start
value.
- Example:
+ Example::
await sum(generator())
-> 1024
@@ -280,7 +349,6 @@
return value
-# pylint: disable=undefined-variable,multiple-statements,too-many-arguments
@overload
def zip(__iter1: AnyIterable[T1]) -> AsyncIterator[Tuple[T1]]: # pragma: no
cover
pass
@@ -334,12 +402,11 @@
pass
-# pylint: enable=undefined-variable,multiple-statements,too-many-arguments
async def zip(*itrs: AnyIterable[Any]) -> AsyncIterator[Tuple[Any, ...]]:
"""
Yield a tuple of items from mixed iterables until the shortest is consumed.
- Example:
+ Example::
async for a, b, c in zip(i, j, k):
...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/aioitertools/helpers.py
new/aioitertools-0.8.0/aioitertools/helpers.py
--- old/aioitertools-0.7.1/aioitertools/helpers.py 2020-11-09
04:47:28.965547800 +0100
+++ new/aioitertools-0.8.0/aioitertools/helpers.py 2021-08-05
04:22:56.191383400 +0200
@@ -2,12 +2,16 @@
# Licensed under the MIT license
import inspect
+import sys
from typing import Awaitable, Union
-from typing_extensions import Protocol
-
from .types import T
+if sys.version_info < (3, 8):
+ from typing_extensions import Protocol
+else:
+ from typing import Protocol
+
class Orderable(Protocol): # pragma: no cover
def __lt__(self, other):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/aioitertools/itertools.py
new/aioitertools-0.8.0/aioitertools/itertools.py
--- old/aioitertools-0.7.1/aioitertools/itertools.py 2020-11-09
04:47:29.179919700 +0100
+++ new/aioitertools-0.8.0/aioitertools/itertools.py 2021-08-05
04:22:56.255954300 +0200
@@ -43,7 +43,7 @@
Accepts both a standard function or a coroutine for accumulation.
- Example:
+ Example::
data = [1, 2, 3, 4]
@@ -73,7 +73,7 @@
Consumes the first iterable lazily, in entirety, then the second, and
so on.
- Example:
+ Example::
async for value in chain([1, 2, 3], [7, 8, 9]):
... # 1, 2, 3, 7, 8, 9
@@ -102,7 +102,7 @@
Simple wrapper around itertools.combinations for asyncio.
This will consume the entire iterable before yielding values.
- Example:
+ Example::
async for value in combinations(range(4), 3):
... # (0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)
@@ -122,7 +122,7 @@
Simple wrapper around itertools.combinations_with_replacement.
This will consume the entire iterable before yielding values.
- Example:
+ Example::
async for value in combinations_with_replacement("ABC", 2):
... # ("A", "A"), ("A", "B"), ("A", "C"), ("B", "B"), ...
@@ -141,7 +141,7 @@
Stops when either the iterable or the selectors have been exhausted.
- Example:
+ Example::
async for value in compress(range(5), [1, 0, 0, 1, 1]):
... # 0, 3, 4
@@ -155,7 +155,7 @@
"""
Yield an infinite series, starting at the given value and increasing by
step.
- Example:
+ Example::
async for value in counter(10, -1):
... # 10, 9, 8, 7, ...
@@ -175,7 +175,7 @@
Lazily consumes the iterable when the next value is needed, and caching
the values in memory for future iterations of the series.
- Example:
+ Example::
async for value in cycle([1, 2]):
... # 1, 2, 1, 2, 1, 2, ...
@@ -199,7 +199,7 @@
Accepts both standard functions and coroutines for the predicate.
- Example:
+ Example::
def pred(x):
return x < 4
@@ -225,7 +225,7 @@
Accepts both standard functions and coroutines for the predicate.
- Example:
+ Example::
def pred(x):
return x < 4
@@ -239,7 +239,6 @@
yield item
-# pylint: disable=undefined-variable,multiple-statements
@overload
def groupby(itr: AnyIterable[T]) -> AsyncIterator[Tuple[T, List[T]]]: #
pragma: nocover
pass
@@ -252,7 +251,6 @@
pass
-# pylint: enable=undefined-variable,multiple-statements
async def groupby(
itr: AnyIterable[T], key: Optional[KeyFunction[T, R]] = None
) -> AsyncIterator[Tuple[Any, List[T]]]:
@@ -264,7 +262,7 @@
coroutines for the key function. Suggest sorting by the key
function before using groupby.
- Example:
+ Example::
data = ["A", "a", "b", "c", "C", "c"]
@@ -274,7 +272,7 @@
"""
if key is None:
- key = lambda x: x
+ key = lambda x: x # noqa: E731
grouping: List[T] = []
@@ -298,7 +296,6 @@
yield j, grouping
-# pylint: disable=undefined-variable,multiple-statements
@overload
def islice(
itr: AnyIterable[T], __stop: Optional[int]
@@ -313,7 +310,6 @@
pass
-# pylint: enable=undefined-variable,multiple-statements
async def islice(itr: AnyIterable[T], *args: Optional[int]) ->
AsyncIterator[T]:
"""
Yield selected items from the given iterable.
@@ -324,7 +320,7 @@
Starting from the start index (or zero), stopping at the stop
index (or until exhausted), skipping items if step > 0.
- Example:
+ Example::
data = range(10)
@@ -372,7 +368,7 @@
Simple wrapper around itertools.combinations for asyncio.
This will consume the entire iterable before yielding values.
- Example:
+ Example::
async for value in permutations(range(3)):
... # (0, 1, 2), (0, 2, 1), (1, 0, 2), ...
@@ -384,7 +380,7 @@
async def product(
- *itrs: AnyIterable[T], repeat: int = 1 # pylint:
disable=redefined-outer-name
+ *itrs: AnyIterable[T], repeat: int = 1
) -> AsyncIterator[Tuple[T, ...]]:
"""
Yield cartesian products of all iterables.
@@ -392,7 +388,7 @@
Simple wrapper around itertools.combinations for asyncio.
This will consume all iterables before yielding any values.
- Example:
+ Example::
async for value in product("abc", "xy"):
... # ("a", "x"), ("a", "y"), ("b", "x"), ...
@@ -410,7 +406,7 @@
"""
Yield the given value repeatedly, forever or up to n times.
- Example:
+ Example::
async for value in repeat(7):
... # 7, 7, 7, 7, 7, 7, ...
@@ -432,7 +428,7 @@
Each iterable contained within will be unpacked and consumed before
executing the function or coroutine.
- Example:
+ Example::
data = [(1, 1), (1, 1, 1), (2, 2)]
@@ -453,7 +449,7 @@
Accepts both standard functions and coroutines for the predicate.
- Example:
+ Example::
def pred(x):
return x < 4
@@ -483,7 +479,7 @@
used in keeping values in the queues until the other iterators finish
consuming them.
- Example:
+ Example::
it1, it2 = tee(range(5), n=2)
@@ -500,15 +496,23 @@
async def gen(k: int, q: asyncio.Queue) -> AsyncIterator[T]:
if k == 0:
- async for value in iter(itr):
- await asyncio.gather(*[queue.put(value) for queue in
queues[1:]])
- yield value
+ try:
+ async for value in iter(itr):
+ await asyncio.gather(
+ *[queue.put((None, value)) for queue in queues[1:]]
+ )
+ yield value
+ except Exception as e:
+ await asyncio.gather(*[queue.put((e, None)) for queue in
queues[1:]])
+ raise
- await asyncio.gather(*[queue.put(sentinel) for queue in
queues[1:]])
+ await asyncio.gather(*[queue.put((None, sentinel)) for queue in
queues[1:]])
else:
while True:
- value = await q.get()
+ error, value = await q.get()
+ if error is not None:
+ raise error
if value is sentinel:
break
yield value
@@ -525,7 +529,7 @@
If shorter iterables are exhausted, the default value will be used
until all iterables are exhausted.
- Example:
+ Example::
a = range(3)
b = range(5)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/aioitertools/more_itertools.py
new/aioitertools-0.8.0/aioitertools/more_itertools.py
--- old/aioitertools-0.7.1/aioitertools/more_itertools.py 2020-11-09
04:47:28.950679500 +0100
+++ new/aioitertools-0.8.0/aioitertools/more_itertools.py 2021-08-05
04:22:56.186720100 +0200
@@ -17,7 +17,7 @@
If there are too few items in iterable, all of them are returned.
n needs to be at least 0. If it is 0, an empty list is returned.
- Example:
+ Example::
first_two = await take(2, [1, 2, 3, 4, 5])
@@ -34,7 +34,7 @@
The last chunk will be shorter if the total number of items is not
divisible by n.
- Example:
+ Example::
async for chunk in chunked([1, 2, 3, 4, 5], n=2):
... # first iteration: chunk == [1, 2]; last one: chunk == [5]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/aioitertools/tests/asyncio.py
new/aioitertools-0.8.0/aioitertools/tests/asyncio.py
--- old/aioitertools-0.7.1/aioitertools/tests/asyncio.py 2020-11-09
04:47:29.478941200 +0100
+++ new/aioitertools-0.8.0/aioitertools/tests/asyncio.py 2021-08-05
04:22:56.366293200 +0200
@@ -59,7 +59,7 @@
fns = [fn(1), asyncio.ensure_future(fn(2))]
if hasattr(asyncio, "create_task"):
# 3.7 only
- fns.append(asyncio.create_task(fn(3))) # pylint: disable=no-member
+ fns.append(asyncio.create_task(fn(3)))
else:
fns.append(fn(3))
@@ -74,8 +74,7 @@
async def fn(arg):
nonlocal counter, max_counter
counter += 1
- if max_counter < counter:
- max_counter = counter
+ max_counter = max(max_counter, counter)
await asyncio.sleep(0.001)
counter -= 1
return arg
@@ -127,3 +126,34 @@
)
self.assertEqual(result[1], 0.001)
self.assertIsInstance(result[0], MyException)
+
+ @async_test
+ async def test_gather_cancel(self):
+ cancelled = False
+ started = False
+
+ async def _fn():
+ nonlocal started, cancelled
+ try:
+ started = True
+ await asyncio.sleep(10) # might as well be forever
+ except asyncio.CancelledError:
+ nonlocal cancelled
+ cancelled = True
+ raise
+
+ async def _gather():
+ await aio.gather(_fn())
+
+ if hasattr(asyncio, "create_task"):
+ # 3.7+ only
+ task = asyncio.create_task(_gather())
+ else:
+ task = asyncio.ensure_future(_gather())
+ # to insure the gather actually runs
+ await asyncio.sleep(0)
+ task.cancel()
+ with self.assertRaises(asyncio.CancelledError):
+ await task
+ self.assertTrue(started)
+ self.assertTrue(cancelled)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/aioitertools/tests/builtins.py
new/aioitertools-0.8.0/aioitertools/tests/builtins.py
--- old/aioitertools-0.7.1/aioitertools/tests/builtins.py 2020-11-09
04:47:29.375778400 +0100
+++ new/aioitertools-0.8.0/aioitertools/tests/builtins.py 2021-08-05
04:22:56.331863200 +0200
@@ -10,10 +10,59 @@
slist = ["A", "B", "C"]
srange = range(3)
+srange1 = range(1, 4)
+srange0 = range(1)
class BuiltinsTest(TestCase):
+ # aioitertools.all()
+
+ @async_test
+ async def test_all_list(self):
+ self.assertTrue(await ait.all([True, 1, "string"]))
+ self.assertFalse(await ait.all([True, 0, "string"]))
+
+ @async_test
+ async def test_all_range(self):
+ self.assertTrue(await ait.all(srange1))
+ self.assertFalse(await ait.all(srange))
+
+ @async_test
+ async def test_all_generator(self):
+ self.assertTrue(await ait.all(x for x in srange1))
+ self.assertFalse(await ait.all(x for x in srange))
+
+ @async_test
+ async def test_all_async_generator(self):
+ self.assertTrue(await ait.all(ait.iter(srange1)))
+ self.assertFalse(await ait.all(ait.iter(srange)))
+
+ # aioitertools.any()
+
+ @async_test
+ async def test_any_list(self):
+ self.assertTrue(await ait.any([False, 1, ""]))
+ self.assertFalse(await ait.any([False, 0, ""]))
+
+ @async_test
+ async def test_any_range(self):
+ self.assertTrue(await ait.any(srange))
+ self.assertTrue(await ait.any(srange1))
+ self.assertFalse(await ait.any(srange0))
+
+ @async_test
+ async def test_any_generator(self):
+ self.assertTrue(await ait.any(x for x in srange))
+ self.assertTrue(await ait.any(x for x in srange1))
+ self.assertFalse(await ait.any(x for x in srange0))
+
+ @async_test
+ async def test_any_async_generator(self):
+ self.assertTrue(await ait.any(ait.iter(srange)))
+ self.assertTrue(await ait.any(ait.iter(srange1)))
+ self.assertFalse(await ait.any(ait.iter(srange0)))
+
# aioitertools.iter()
@async_test
@@ -134,6 +183,21 @@
with self.assertRaises(StopAsyncIteration):
await ait.next(it)
+ @async_test
+ async def test_next_default_iterable(self):
+ it = iter(["A"])
+
+ self.assertEqual(await ait.next(it, "?"), "A")
+ # End of iteration
+ self.assertEqual(await ait.next(it, "?"), "?")
+
+ @async_test
+ async def test_next_default_async_iterable(self):
+ it = ait.iter(["A"])
+ self.assertEqual(await ait.next(it, "?"), "A")
+ # End of iteration
+ self.assertEqual(await ait.next(it, "?"), "?")
+
# aioitertools.list()
@async_test
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/aioitertools/tests/itertools.py
new/aioitertools-0.8.0/aioitertools/tests/itertools.py
--- old/aioitertools-0.7.1/aioitertools/tests/itertools.py 2020-11-09
04:47:30.139533000 +0100
+++ new/aioitertools-0.8.0/aioitertools/tests/itertools.py 2021-08-05
04:22:56.567801200 +0200
@@ -695,6 +695,33 @@
await ait.next(it)
@async_test
+ async def test_tee_propagate_exception(self):
+ class MyError(Exception):
+ pass
+
+ async def gen():
+ yield 1
+ yield 2
+ raise MyError
+
+ async def consumer(it):
+ result = 0
+ async for item in it:
+ result += item
+ return result
+
+ it1, it2 = ait.tee(gen())
+
+ values = await asyncio.gather(
+ consumer(it1),
+ consumer(it2),
+ return_exceptions=True,
+ )
+
+ for value in values:
+ self.assertIsInstance(value, MyError)
+
+ @async_test
async def test_zip_longest_range(self):
a = range(3)
b = range(5)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/aioitertools-0.7.1/aioitertools/tests/more_itertools.py
new/aioitertools-0.8.0/aioitertools/tests/more_itertools.py
--- old/aioitertools-0.7.1/aioitertools/tests/more_itertools.py 2020-11-09
04:47:29.533481100 +0100
+++ new/aioitertools-0.8.0/aioitertools/tests/more_itertools.py 2021-08-05
04:22:56.383290300 +0200
@@ -15,7 +15,7 @@
async def _empty() -> AsyncIterable[int]:
return
- yield 0 # pylint: disable=unreachable
+ yield 0
class MoreItertoolsTest(TestCase):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/aioitertools/types.py
new/aioitertools-0.8.0/aioitertools/types.py
--- old/aioitertools-0.7.1/aioitertools/types.py 2020-11-09
04:47:28.931515000 +0100
+++ new/aioitertools-0.8.0/aioitertools/types.py 2021-08-05
04:22:56.181237700 +0200
@@ -29,3 +29,4 @@
Accumulator = Union[Callable[[T, T], T], Callable[[T, T], Awaitable[T]]]
KeyFunction = Union[Callable[[T], R], Callable[[T], Awaitable[R]]]
Predicate = Union[Callable[[T], object], Callable[[T], Awaitable[object]]]
+MaybeAwaitable = Union[T, Awaitable[T]]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/docs/_static/custom.css
new/aioitertools-0.8.0/docs/_static/custom.css
--- old/aioitertools-0.7.1/docs/_static/custom.css 2020-05-01
03:16:20.685631300 +0200
+++ new/aioitertools-0.8.0/docs/_static/custom.css 2021-05-16
22:28:42.578924400 +0200
@@ -17,4 +17,8 @@
div.omnilib-badges a:hover {
color: #777;
border: none;
-}
\ No newline at end of file
+}
+
+dl.class, dl.function, dl.attribute {
+ margin-bottom: 15px;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/docs/conf.py
new/aioitertools-0.8.0/docs/conf.py
--- old/aioitertools-0.7.1/docs/conf.py 2020-05-01 03:20:29.020955000 +0200
+++ new/aioitertools-0.8.0/docs/conf.py 2021-08-05 03:54:56.994592200 +0200
@@ -35,6 +35,14 @@
"sphinx.ext.intersphinx",
]
+autodoc_default_options = {
+ "show-inheritance": True,
+ "members": True,
+ "inherited-members": True,
+}
+autodoc_member_order = "bysource"
+autodoc_typehints = "description"
+
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/makefile
new/aioitertools-0.8.0/makefile
--- old/aioitertools-0.7.1/makefile 2020-11-09 00:25:34.085005300 +0100
+++ new/aioitertools-0.8.0/makefile 2021-05-16 23:04:10.655338300 +0200
@@ -22,7 +22,7 @@
python -m black aioitertools
lint:
- python -m pylint --rcfile .pylint aioitertools
+ python -m flake8 aioitertools
python -m usort check aioitertools
python -m black --check aioitertools
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/pyproject.toml
new/aioitertools-0.8.0/pyproject.toml
--- old/aioitertools-0.7.1/pyproject.toml 2020-11-09 04:54:38.147944200
+0100
+++ new/aioitertools-0.8.0/pyproject.toml 2021-03-07 00:15:44.518752300
+0100
@@ -8,7 +8,7 @@
author-email = "[email protected]"
description-file = "README.md"
home-page = "https://aioitertools.omnilib.dev"
-requires = ["typing_extensions>=3.7"]
+requires = ["typing_extensions>=3.7; python_version < '3.8'"]
requires-python = ">=3.6"
classifiers = [
"Development Status :: 4 - Beta",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/requirements-dev.txt
new/aioitertools-0.8.0/requirements-dev.txt
--- old/aioitertools-0.7.1/requirements-dev.txt 2020-11-09 04:44:53.892360200
+0100
+++ new/aioitertools-0.8.0/requirements-dev.txt 2021-08-05 03:56:49.667648300
+0200
@@ -1,10 +1,10 @@
-attribution==1.4.0
-black==20.8b1
-codecov==2.1.10
-coverage[toml]==5.3
-flit==3.0.0
-mypy==0.790
-pylint==2.4.4 # pyup: <2.5
-sphinx==3.3.0
-usort==0.6.0
+attribution==1.5.2
+black==21.7b0
+codecov==2.1.11
+coverage[toml]==5.5
+flake8==3.9.2
+flit==3.2.0
+mypy==0.910
+sphinx==4.1.1
+usort==0.6.2
git+https://github.com/miyakogi/m2r@66f4a5a500cdd9fc59085106bff082c9cadafaf3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/requirements.txt
new/aioitertools-0.8.0/requirements.txt
--- old/aioitertools-0.7.1/requirements.txt 2020-05-06 04:47:36.350556000
+0200
+++ new/aioitertools-0.8.0/requirements.txt 2021-03-07 00:15:44.519299500
+0100
@@ -1 +1 @@
-typing_extensions>=3.7
\ No newline at end of file
+typing_extensions>=3.7;python_version<"3.8"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/aioitertools-0.7.1/setup.py
new/aioitertools-0.8.0/setup.py
--- old/aioitertools-0.7.1/setup.py 1970-01-01 01:00:00.000000000 +0100
+++ new/aioitertools-0.8.0/setup.py 1970-01-01 01:00:00.000000000 +0100
@@ -9,17 +9,17 @@
package_data = \
{'': ['*']}
-install_requires = \
-['typing_extensions>=3.7']
+extras_require = \
+{":python_version < '3.8'": ['typing_extensions>=3.7']}
setup(name='aioitertools',
- version='0.7.1',
+ version='0.8.0',
description='itertools and builtins for AsyncIO and mixed iterables',
author='John Reese',
author_email='[email protected]',
url='https://aioitertools.omnilib.dev',
packages=packages,
package_data=package_data,
- install_requires=install_requires,
+ extras_require=extras_require,
python_requires='>=3.6',
)