ez-a-sync 0.22.14__py3-none-any.whl → 0.22.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ez-a-sync might be problematic. Click here for more details.
- a_sync/ENVIRONMENT_VARIABLES.py +37 -5
- a_sync/__init__.py +53 -12
- a_sync/_smart.py +231 -28
- a_sync/_typing.py +112 -15
- a_sync/a_sync/__init__.py +35 -10
- a_sync/a_sync/_descriptor.py +248 -38
- a_sync/a_sync/_flags.py +78 -9
- a_sync/a_sync/_helpers.py +46 -13
- a_sync/a_sync/_kwargs.py +33 -8
- a_sync/a_sync/_meta.py +149 -28
- a_sync/a_sync/abstract.py +150 -28
- a_sync/a_sync/base.py +34 -16
- a_sync/a_sync/config.py +85 -14
- a_sync/a_sync/decorator.py +441 -139
- a_sync/a_sync/function.py +709 -147
- a_sync/a_sync/method.py +437 -110
- a_sync/a_sync/modifiers/__init__.py +85 -5
- a_sync/a_sync/modifiers/cache/__init__.py +116 -17
- a_sync/a_sync/modifiers/cache/memory.py +130 -20
- a_sync/a_sync/modifiers/limiter.py +101 -22
- a_sync/a_sync/modifiers/manager.py +142 -16
- a_sync/a_sync/modifiers/semaphores.py +121 -15
- a_sync/a_sync/property.py +383 -82
- a_sync/a_sync/singleton.py +44 -19
- a_sync/aliases.py +0 -1
- a_sync/asyncio/__init__.py +140 -1
- a_sync/asyncio/as_completed.py +213 -79
- a_sync/asyncio/create_task.py +70 -20
- a_sync/asyncio/gather.py +125 -58
- a_sync/asyncio/utils.py +3 -3
- a_sync/exceptions.py +248 -26
- a_sync/executor.py +164 -69
- a_sync/future.py +1227 -168
- a_sync/iter.py +173 -56
- a_sync/primitives/__init__.py +14 -2
- a_sync/primitives/_debug.py +72 -18
- a_sync/primitives/_loggable.py +41 -10
- a_sync/primitives/locks/__init__.py +5 -2
- a_sync/primitives/locks/counter.py +107 -38
- a_sync/primitives/locks/event.py +21 -7
- a_sync/primitives/locks/prio_semaphore.py +262 -63
- a_sync/primitives/locks/semaphore.py +138 -89
- a_sync/primitives/queue.py +601 -60
- a_sync/sphinx/__init__.py +0 -1
- a_sync/sphinx/ext.py +160 -50
- a_sync/task.py +313 -112
- a_sync/utils/__init__.py +12 -6
- a_sync/utils/iterators.py +170 -50
- {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/METADATA +1 -1
- ez_a_sync-0.22.16.dist-info/RECORD +74 -0
- {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/WHEEL +1 -1
- tests/conftest.py +1 -2
- tests/executor.py +250 -9
- tests/fixtures.py +61 -32
- tests/test_abstract.py +22 -4
- tests/test_as_completed.py +54 -21
- tests/test_base.py +264 -19
- tests/test_cache.py +31 -15
- tests/test_decorator.py +54 -28
- tests/test_executor.py +31 -13
- tests/test_future.py +45 -8
- tests/test_gather.py +8 -2
- tests/test_helpers.py +2 -0
- tests/test_iter.py +55 -13
- tests/test_limiter.py +5 -3
- tests/test_meta.py +23 -9
- tests/test_modified.py +4 -1
- tests/test_semaphore.py +15 -8
- tests/test_singleton.py +28 -11
- tests/test_task.py +162 -36
- ez_a_sync-0.22.14.dist-info/RECORD +0 -74
- {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/LICENSE.txt +0 -0
- {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/top_level.txt +0 -0
a_sync/a_sync/singleton.py
CHANGED
|
@@ -1,36 +1,61 @@
|
|
|
1
1
|
from a_sync.a_sync._meta import ASyncSingletonMeta
|
|
2
2
|
from a_sync.a_sync.base import ASyncGenericBase
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
class ASyncGenericSingleton(ASyncGenericBase, metaclass=ASyncSingletonMeta):
|
|
5
6
|
"""
|
|
6
7
|
A base class for creating singleton-esque ASync classes.
|
|
7
8
|
|
|
8
|
-
This class combines the functionality of ASyncGenericBase with a singleton pattern,
|
|
9
|
+
This class combines the functionality of :class:`ASyncGenericBase` with a singleton pattern,
|
|
9
10
|
ensuring that only one instance of the class exists per execution mode (sync/async).
|
|
10
|
-
It uses a custom metaclass to manage instance creation and caching.
|
|
11
|
+
It uses a custom metaclass :class:`ASyncSingletonMeta` to manage instance creation and caching.
|
|
11
12
|
|
|
12
|
-
Subclasses of ASyncGenericSingleton will have two instances instead of one:
|
|
13
|
+
Subclasses of :class:`ASyncGenericSingleton` will have two instances instead of one:
|
|
13
14
|
- one synchronous instance
|
|
14
15
|
- one asynchronous instance
|
|
15
16
|
|
|
16
17
|
This allows for proper behavior in both synchronous and asynchronous contexts
|
|
17
18
|
while maintaining the singleton pattern within each context.
|
|
18
19
|
|
|
20
|
+
Note:
|
|
21
|
+
This class is abstract and cannot be instantiated directly. Subclasses should define
|
|
22
|
+
the necessary properties and methods to specify the asynchronous behavior, as outlined
|
|
23
|
+
in :class:`ASyncABC`.
|
|
24
|
+
|
|
19
25
|
Example:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
.. code-block:: python
|
|
27
|
+
|
|
28
|
+
class MyAsyncSingleton(ASyncGenericSingleton):
|
|
29
|
+
@property
|
|
30
|
+
def __a_sync_flag_name__(self):
|
|
31
|
+
return "asynchronous"
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def __a_sync_flag_value__(self):
|
|
35
|
+
return self.asynchronous
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def __a_sync_default_mode__(cls):
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
@a_sync
|
|
42
|
+
def my_method(self):
|
|
43
|
+
# Method implementation
|
|
44
|
+
|
|
45
|
+
# These will return the same synchronous instance
|
|
46
|
+
sync_instance1 = MyAsyncSingleton(sync=True)
|
|
47
|
+
sync_instance2 = MyAsyncSingleton(sync=True)
|
|
48
|
+
|
|
49
|
+
# These will return the same asynchronous instance
|
|
50
|
+
async_instance1 = MyAsyncSingleton(asynchronous=True)
|
|
51
|
+
async_instance2 = MyAsyncSingleton(asynchronous=True)
|
|
52
|
+
|
|
53
|
+
assert sync_instance1 is sync_instance2
|
|
54
|
+
assert async_instance1 is async_instance2
|
|
55
|
+
assert sync_instance1 is not async_instance1
|
|
56
|
+
|
|
57
|
+
See Also:
|
|
58
|
+
- :class:`ASyncGenericBase` for base functionality.
|
|
59
|
+
- :class:`ASyncSingletonMeta` for the metaclass managing the singleton behavior.
|
|
60
|
+
- :class:`ASyncABC` for defining asynchronous and synchronous behavior.
|
|
36
61
|
"""
|
a_sync/aliases.py
CHANGED
a_sync/asyncio/__init__.py
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
"""
|
|
2
|
-
This package
|
|
2
|
+
This package provides custom utilities and extensions to the built-in `asyncio` package.
|
|
3
|
+
|
|
4
|
+
These utilities include enhanced versions of common asyncio functions, offering additional
|
|
5
|
+
features and improved functionality for asynchronous programming.
|
|
6
|
+
|
|
7
|
+
Modules:
|
|
8
|
+
- :func:`create_task`: Extends `asyncio.create_task` to support any `Awaitable`, manage task lifecycle, and enhance error handling.
|
|
9
|
+
- :func:`gather`: Provides an enhanced version of `asyncio.gather` with additional features like progress reporting and exclusion of results based on a condition.
|
|
10
|
+
- :func:`as_completed`: Extends `asyncio.as_completed` with additional functionality such as progress reporting using `tqdm`.
|
|
11
|
+
- :func:`get_event_loop`: Utility to get the current event loop, handling cases where no current event loop exists by raising a `RuntimeError`.
|
|
12
|
+
|
|
13
|
+
See Also:
|
|
14
|
+
- `asyncio <https://docs.python.org/3/library/asyncio.html>`_: The standard asyncio library documentation for more details on the original functions.
|
|
3
15
|
"""
|
|
4
16
|
|
|
5
17
|
from a_sync.asyncio.as_completed import as_completed
|
|
@@ -8,3 +20,130 @@ from a_sync.asyncio.gather import gather
|
|
|
8
20
|
from a_sync.asyncio.utils import get_event_loop
|
|
9
21
|
|
|
10
22
|
__all__ = ["create_task", "gather", "as_completed", "get_event_loop"]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# Function: create_task
|
|
26
|
+
"""
|
|
27
|
+
Extends `asyncio.create_task` to support any `Awaitable`, manage task lifecycle, and enhance error handling.
|
|
28
|
+
|
|
29
|
+
This function accepts any `Awaitable`, ensuring broader compatibility. If the `Awaitable` is not a coroutine,
|
|
30
|
+
it attempts to convert it to one. It optionally prevents the task from being garbage-collected until completion
|
|
31
|
+
and provides enhanced error management by wrapping exceptions in a custom exception when `skip_gc_until_done` is True.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
coro: An `Awaitable` object from which to create the task. If not a coroutine, it will be converted.
|
|
35
|
+
name: Optional name for the task, aiding in debugging.
|
|
36
|
+
skip_gc_until_done: If True, the task is kept alive until it completes, preventing garbage collection.
|
|
37
|
+
Exceptions are wrapped in `PersistedTaskException` for special handling.
|
|
38
|
+
log_destroy_pending: If False, asyncio's default error log when a pending task is destroyed is suppressed.
|
|
39
|
+
|
|
40
|
+
Examples:
|
|
41
|
+
Basic usage:
|
|
42
|
+
```
|
|
43
|
+
task = create_task(some_coroutine())
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
With options:
|
|
47
|
+
```
|
|
48
|
+
task = create_task(some_coroutine(), name="MyTask", skip_gc_until_done=True)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
See Also:
|
|
52
|
+
- :func:`asyncio.create_task`: The original asyncio function.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# Function: gather
|
|
57
|
+
"""
|
|
58
|
+
Provides an enhanced version of :func:`asyncio.gather`.
|
|
59
|
+
|
|
60
|
+
This function extends Python's `asyncio.gather`, providing additional features for handling either individual awaitable objects or a mapping of awaitables.
|
|
61
|
+
|
|
62
|
+
Differences from `asyncio.gather`:
|
|
63
|
+
- Uses type hints for use with static type checkers.
|
|
64
|
+
- Supports gathering either individual awaitables or a k:v mapping of awaitables.
|
|
65
|
+
- Provides progress reporting using `tqdm` if 'tqdm' is set to True.
|
|
66
|
+
- Allows exclusion of results based on a condition using the 'exclude_if' parameter.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
*awaitables: The awaitables to await concurrently. It can be a list of individual awaitables or a mapping of awaitables.
|
|
70
|
+
return_exceptions: If True, exceptions are returned as results instead of raising them. Defaults to False.
|
|
71
|
+
exclude_if: A callable that takes a result and returns True if the result should be excluded from the final output. Defaults to None.
|
|
72
|
+
tqdm: If True, enables progress reporting using `tqdm`. Defaults to False.
|
|
73
|
+
**tqdm_kwargs: Additional keyword arguments for `tqdm` if progress reporting is enabled.
|
|
74
|
+
|
|
75
|
+
Examples:
|
|
76
|
+
Awaiting individual awaitables:
|
|
77
|
+
```
|
|
78
|
+
results = await gather(thing1(), thing2())
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Awaiting a mapping of awaitables:
|
|
82
|
+
```
|
|
83
|
+
mapping = {'key1': thing1(), 'key2': thing2()}
|
|
84
|
+
results = await gather(mapping)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
See Also:
|
|
88
|
+
- :func:`asyncio.gather`: The original asyncio function.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# Function: as_completed
|
|
93
|
+
"""
|
|
94
|
+
Extends Python's :func:`asyncio.as_completed` with additional functionality.
|
|
95
|
+
|
|
96
|
+
This function extends Python's `asyncio.as_completed`, providing additional features for mixed use cases of individual awaitable objects and mappings of awaitables.
|
|
97
|
+
|
|
98
|
+
Differences from `asyncio.as_completed`:
|
|
99
|
+
- Uses type hints for use with static type checkers.
|
|
100
|
+
- Supports either individual awaitables or a k:v mapping of awaitables.
|
|
101
|
+
- Can be used as an async iterator which yields the result values.
|
|
102
|
+
- Provides progress reporting using `tqdm` if 'tqdm' is set to True.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
fs: The awaitables to await concurrently. It can be a list of individual awaitables or a mapping of awaitables.
|
|
106
|
+
timeout: The maximum time, in seconds, to wait for the completion of awaitables. Defaults to None (no timeout).
|
|
107
|
+
return_exceptions: If True, exceptions are returned as results instead of raising them. Defaults to False.
|
|
108
|
+
aiter: If True, returns an async iterator of results. Defaults to False.
|
|
109
|
+
tqdm: If True, enables progress reporting using `tqdm`. Defaults to False.
|
|
110
|
+
**tqdm_kwargs: Additional keyword arguments for `tqdm` if progress reporting is enabled.
|
|
111
|
+
|
|
112
|
+
Examples:
|
|
113
|
+
Awaiting individual awaitables:
|
|
114
|
+
```
|
|
115
|
+
awaitables = [async_function1(), async_function2()]
|
|
116
|
+
for coro in as_completed(awaitables):
|
|
117
|
+
val = await coro
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Awaiting mappings of awaitables:
|
|
121
|
+
```
|
|
122
|
+
mapping = {'key1': async_function1(), 'key2': async_function2()}
|
|
123
|
+
for coro in as_completed(mapping):
|
|
124
|
+
k, v = await coro
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
See Also:
|
|
128
|
+
- :func:`asyncio.as_completed`: The original asyncio function.
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# Function: get_event_loop
|
|
133
|
+
"""
|
|
134
|
+
Utility to get the current event loop, handling cases where no current event loop exists by raising a `RuntimeError`.
|
|
135
|
+
|
|
136
|
+
This function attempts to get the current event loop. If no event loop is found (which can occur in multi-threaded applications), it raises a `RuntimeError`.
|
|
137
|
+
|
|
138
|
+
Examples:
|
|
139
|
+
Basic usage:
|
|
140
|
+
```
|
|
141
|
+
try:
|
|
142
|
+
loop = get_event_loop()
|
|
143
|
+
except RuntimeError:
|
|
144
|
+
print("No current event loop found.")
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
See Also:
|
|
148
|
+
- :func:`asyncio.get_event_loop`: The original asyncio function.
|
|
149
|
+
"""
|
a_sync/asyncio/as_completed.py
CHANGED
|
@@ -7,134 +7,267 @@ import asyncio
|
|
|
7
7
|
try:
|
|
8
8
|
from tqdm.asyncio import tqdm_asyncio
|
|
9
9
|
except ImportError as e:
|
|
10
|
+
|
|
10
11
|
class tqdm_asyncio: # type: ignore [no-redef]
|
|
12
|
+
@staticmethod
|
|
11
13
|
def as_completed(*args, **kwargs):
|
|
12
14
|
raise ImportError("You must have tqdm installed to use this feature")
|
|
13
|
-
|
|
15
|
+
|
|
16
|
+
|
|
14
17
|
from a_sync._typing import *
|
|
15
18
|
from a_sync.iter import ASyncIterator
|
|
16
19
|
|
|
20
|
+
|
|
17
21
|
@overload
|
|
18
|
-
def as_completed(
|
|
19
|
-
|
|
22
|
+
def as_completed(
|
|
23
|
+
fs: Iterable[Awaitable[T]],
|
|
24
|
+
*,
|
|
25
|
+
timeout: Optional[float] = None,
|
|
26
|
+
return_exceptions: bool = False,
|
|
27
|
+
aiter: Literal[False] = False,
|
|
28
|
+
tqdm: bool = False,
|
|
29
|
+
**tqdm_kwargs: Any
|
|
30
|
+
) -> Iterator[Coroutine[Any, Any, T]]: ...
|
|
20
31
|
@overload
|
|
21
|
-
def as_completed(
|
|
22
|
-
|
|
32
|
+
def as_completed(
|
|
33
|
+
fs: Iterable[Awaitable[T]],
|
|
34
|
+
*,
|
|
35
|
+
timeout: Optional[float] = None,
|
|
36
|
+
return_exceptions: bool = False,
|
|
37
|
+
aiter: Literal[True] = True,
|
|
38
|
+
tqdm: bool = False,
|
|
39
|
+
**tqdm_kwargs: Any
|
|
40
|
+
) -> ASyncIterator[T]: ...
|
|
23
41
|
@overload
|
|
24
|
-
def as_completed(
|
|
25
|
-
|
|
42
|
+
def as_completed(
|
|
43
|
+
fs: Mapping[K, Awaitable[V]],
|
|
44
|
+
*,
|
|
45
|
+
timeout: Optional[float] = None,
|
|
46
|
+
return_exceptions: bool = False,
|
|
47
|
+
aiter: Literal[False] = False,
|
|
48
|
+
tqdm: bool = False,
|
|
49
|
+
**tqdm_kwargs: Any
|
|
50
|
+
) -> Iterator[Coroutine[Any, Any, Tuple[K, V]]]: ...
|
|
26
51
|
@overload
|
|
27
|
-
def as_completed(
|
|
28
|
-
|
|
29
|
-
|
|
52
|
+
def as_completed(
|
|
53
|
+
fs: Mapping[K, Awaitable[V]],
|
|
54
|
+
*,
|
|
55
|
+
timeout: Optional[float] = None,
|
|
56
|
+
return_exceptions: bool = False,
|
|
57
|
+
aiter: Literal[True] = True,
|
|
58
|
+
tqdm: bool = False,
|
|
59
|
+
**tqdm_kwargs: Any
|
|
60
|
+
) -> ASyncIterator[Tuple[K, V]]: ...
|
|
61
|
+
def as_completed(
|
|
62
|
+
fs,
|
|
63
|
+
*,
|
|
64
|
+
timeout: Optional[float] = None,
|
|
65
|
+
return_exceptions: bool = False,
|
|
66
|
+
aiter: bool = False,
|
|
67
|
+
tqdm: bool = False,
|
|
68
|
+
**tqdm_kwargs: Any
|
|
69
|
+
):
|
|
30
70
|
"""
|
|
31
71
|
Concurrently awaits a list of awaitable objects or mappings of awaitables and returns an iterator of results.
|
|
32
72
|
|
|
33
|
-
This function extends Python's asyncio.as_completed
|
|
73
|
+
This function extends Python's :func:`asyncio.as_completed`, providing additional features for mixed use cases of individual awaitable objects and mappings of awaitables.
|
|
34
74
|
|
|
35
|
-
Differences from asyncio.as_completed
|
|
75
|
+
Differences from :func:`asyncio.as_completed`:
|
|
36
76
|
- Uses type hints for use with static type checkers.
|
|
37
77
|
- Supports either individual awaitables or a k:v mapping of awaitables.
|
|
38
|
-
- Can be used as an async iterator which yields the result values.
|
|
39
|
-
- Provides progress reporting using tqdm if 'tqdm' is set to True.
|
|
78
|
+
- Can be used as an async iterator which yields the result values.
|
|
79
|
+
- Provides progress reporting using :mod:`tqdm` if 'tqdm' is set to True.
|
|
40
80
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
timeout (float, optional): The maximum time, in seconds, to wait for the completion of awaitables. Defaults to None (no timeout).
|
|
44
|
-
return_exceptions (bool, optional): If True, exceptions are returned as results instead of raising them. Defaults to False.
|
|
45
|
-
aiter (bool, optional): If True, returns an async iterator of results. Defaults to False.
|
|
46
|
-
tqdm (bool, optional): If True, enables progress reporting using tqdm. Defaults to False.
|
|
47
|
-
**tqdm_kwargs: Additional keyword arguments for tqdm if progress reporting is enabled.
|
|
81
|
+
Note:
|
|
82
|
+
The `return_exceptions` parameter is partially implemented. While exceptions can be wrapped and returned instead of being raised, this behavior may not be fully consistent across all scenarios. Users should test their specific use cases to ensure the desired behavior.
|
|
48
83
|
|
|
49
|
-
|
|
50
|
-
|
|
84
|
+
Args:
|
|
85
|
+
fs: The awaitables to await concurrently. It can be a list of individual awaitables or a mapping of awaitables.
|
|
86
|
+
timeout: The maximum time, in seconds, to wait for the completion of awaitables. Defaults to None (no timeout).
|
|
87
|
+
return_exceptions: If True, exceptions are wrapped and returned as results instead of raising them. Defaults to False.
|
|
88
|
+
aiter: If True, returns an async iterator of results. Defaults to False.
|
|
89
|
+
tqdm: If True, enables progress reporting using :mod:`tqdm`. Defaults to False.
|
|
90
|
+
**tqdm_kwargs: Additional keyword arguments for :mod:`tqdm` if progress reporting is enabled.
|
|
51
91
|
|
|
52
92
|
Examples:
|
|
53
93
|
Awaiting individual awaitables:
|
|
54
|
-
|
|
55
|
-
awaitables = [async_function1(), async_function2()]
|
|
56
|
-
for coro in as_completed(awaitables):
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
async for val in as_completed(awaitables, aiter=True):
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
94
|
+
|
|
95
|
+
>>> awaitables = [async_function1(), async_function2()]
|
|
96
|
+
>>> for coro in as_completed(awaitables):
|
|
97
|
+
... val = await coro
|
|
98
|
+
... ...
|
|
99
|
+
|
|
100
|
+
>>> async for val in as_completed(awaitables, aiter=True):
|
|
101
|
+
... ...
|
|
102
|
+
|
|
64
103
|
Awaiting mappings of awaitables:
|
|
65
|
-
|
|
66
|
-
mapping = {'key1': async_function1(), 'key2': async_function2()}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
104
|
+
|
|
105
|
+
>>> mapping = {'key1': async_function1(), 'key2': async_function2()}
|
|
106
|
+
>>> for coro in as_completed(mapping):
|
|
107
|
+
... k, v = await coro
|
|
108
|
+
... ...
|
|
109
|
+
|
|
110
|
+
>>> async for k, v in as_completed(mapping, aiter=True):
|
|
111
|
+
... ...
|
|
112
|
+
|
|
113
|
+
See Also:
|
|
114
|
+
- :func:`asyncio.as_completed`
|
|
115
|
+
- :class:`ASyncIterator`
|
|
75
116
|
"""
|
|
76
117
|
if isinstance(fs, Mapping):
|
|
77
|
-
return as_completed_mapping(
|
|
118
|
+
return as_completed_mapping(
|
|
119
|
+
fs,
|
|
120
|
+
timeout=timeout,
|
|
121
|
+
return_exceptions=return_exceptions,
|
|
122
|
+
aiter=aiter,
|
|
123
|
+
tqdm=tqdm,
|
|
124
|
+
**tqdm_kwargs
|
|
125
|
+
)
|
|
78
126
|
if return_exceptions:
|
|
79
127
|
fs = [_exc_wrap(f) for f in fs]
|
|
80
128
|
return (
|
|
81
|
-
ASyncIterator(
|
|
82
|
-
|
|
83
|
-
|
|
129
|
+
ASyncIterator(
|
|
130
|
+
__yield_as_completed(fs, timeout=timeout, tqdm=tqdm, **tqdm_kwargs)
|
|
131
|
+
)
|
|
132
|
+
if aiter
|
|
133
|
+
else (
|
|
134
|
+
tqdm_asyncio.as_completed(fs, timeout=timeout, **tqdm_kwargs)
|
|
135
|
+
if tqdm
|
|
136
|
+
else asyncio.as_completed(fs, timeout=timeout)
|
|
137
|
+
)
|
|
84
138
|
)
|
|
85
139
|
|
|
140
|
+
|
|
86
141
|
@overload
|
|
87
|
-
def as_completed_mapping(
|
|
88
|
-
|
|
142
|
+
def as_completed_mapping(
|
|
143
|
+
mapping: Mapping[K, Awaitable[V]],
|
|
144
|
+
*,
|
|
145
|
+
timeout: Optional[float] = None,
|
|
146
|
+
return_exceptions: bool = False,
|
|
147
|
+
aiter: Literal[True] = True,
|
|
148
|
+
tqdm: bool = False,
|
|
149
|
+
**tqdm_kwargs: Any
|
|
150
|
+
) -> ASyncIterator[Tuple[K, V]]: ...
|
|
89
151
|
@overload
|
|
90
|
-
def as_completed_mapping(
|
|
91
|
-
|
|
92
|
-
|
|
152
|
+
def as_completed_mapping(
|
|
153
|
+
mapping: Mapping[K, Awaitable[V]],
|
|
154
|
+
*,
|
|
155
|
+
timeout: Optional[float] = None,
|
|
156
|
+
return_exceptions: bool = False,
|
|
157
|
+
aiter: Literal[False] = False,
|
|
158
|
+
tqdm: bool = False,
|
|
159
|
+
**tqdm_kwargs: Any
|
|
160
|
+
) -> Iterator[Coroutine[Any, Any, Tuple[K, V]]]: ...
|
|
161
|
+
def as_completed_mapping(
|
|
162
|
+
mapping: Mapping[K, Awaitable[V]],
|
|
163
|
+
*,
|
|
164
|
+
timeout: Optional[float] = None,
|
|
165
|
+
return_exceptions: bool = False,
|
|
166
|
+
aiter: bool = False,
|
|
167
|
+
tqdm: bool = False,
|
|
168
|
+
**tqdm_kwargs: Any
|
|
169
|
+
) -> Union[Iterator[Coroutine[Any, Any, Tuple[K, V]]], ASyncIterator[Tuple[K, V]]]:
|
|
93
170
|
"""
|
|
94
171
|
Concurrently awaits a mapping of awaitable objects and returns an iterator or async iterator of results.
|
|
95
172
|
|
|
96
173
|
This function is designed to await a mapping of awaitable objects, where each key-value pair represents a unique awaitable. It enables concurrent execution and gathers results into an iterator or an async iterator.
|
|
97
174
|
|
|
98
175
|
Args:
|
|
99
|
-
mapping
|
|
100
|
-
timeout
|
|
101
|
-
return_exceptions
|
|
102
|
-
aiter
|
|
103
|
-
tqdm
|
|
104
|
-
**tqdm_kwargs: Additional keyword arguments for tqdm if progress reporting is enabled.
|
|
105
|
-
|
|
106
|
-
Returns:
|
|
107
|
-
Union[Iterator[Coroutine[Any, Any, Tuple[K, V]]] or ASyncIterator[Tuple[K, V]]]: An iterator of results or an async iterator when awaiting mappings.
|
|
176
|
+
mapping: A dictionary-like object where keys are of type K and values are awaitable objects of type V.
|
|
177
|
+
timeout: The maximum time, in seconds, to wait for the completion of awaitables. Defaults to None (no timeout).
|
|
178
|
+
return_exceptions: If True, exceptions are wrapped and returned as results instead of raising them. Defaults to False.
|
|
179
|
+
aiter: If True, returns an async iterator of results. Defaults to False.
|
|
180
|
+
tqdm: If True, enables progress reporting using :mod:`tqdm`. Defaults to False.
|
|
181
|
+
**tqdm_kwargs: Additional keyword arguments for :mod:`tqdm` if progress reporting is enabled.
|
|
108
182
|
|
|
109
183
|
Example:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
184
|
+
>>> mapping = {'key1': async_function1(), 'key2': async_function2()}
|
|
185
|
+
>>> for coro in as_completed_mapping(mapping):
|
|
186
|
+
... k, v = await coro
|
|
187
|
+
... ...
|
|
188
|
+
|
|
189
|
+
>>> async for k, v in as_completed_mapping(mapping, aiter=True):
|
|
190
|
+
... ...
|
|
191
|
+
|
|
192
|
+
See Also:
|
|
193
|
+
- :func:`as_completed`
|
|
194
|
+
- :class:`ASyncIterator`
|
|
120
195
|
"""
|
|
121
|
-
return as_completed(
|
|
196
|
+
return as_completed(
|
|
197
|
+
[
|
|
198
|
+
__mapping_wrap(k, v, return_exceptions=return_exceptions)
|
|
199
|
+
for k, v in mapping.items()
|
|
200
|
+
],
|
|
201
|
+
timeout=timeout,
|
|
202
|
+
aiter=aiter,
|
|
203
|
+
tqdm=tqdm,
|
|
204
|
+
**tqdm_kwargs
|
|
205
|
+
)
|
|
206
|
+
|
|
122
207
|
|
|
123
208
|
async def _exc_wrap(awaitable: Awaitable[T]) -> Union[T, Exception]:
|
|
209
|
+
"""Wraps an awaitable to catch exceptions and return them instead of raising.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
awaitable: The awaitable to wrap.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
The result of the awaitable or the exception if one is raised.
|
|
216
|
+
"""
|
|
124
217
|
try:
|
|
125
218
|
return await awaitable
|
|
126
219
|
except Exception as e:
|
|
127
220
|
return e
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
async def __yield_as_completed(
|
|
224
|
+
futs: Iterable[Awaitable[T]],
|
|
225
|
+
*,
|
|
226
|
+
timeout: Optional[float] = None,
|
|
227
|
+
return_exceptions: bool = False,
|
|
228
|
+
tqdm: bool = False,
|
|
229
|
+
**tqdm_kwargs: Any
|
|
230
|
+
) -> AsyncIterator[T]:
|
|
231
|
+
"""Yields results from awaitables as they complete.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
futs: The awaitables to await.
|
|
235
|
+
timeout: The maximum time, in seconds, to wait for the completion of awaitables. Defaults to None (no timeout).
|
|
236
|
+
return_exceptions: If True, exceptions are wrapped and returned as results instead of raising them. Defaults to False.
|
|
237
|
+
tqdm: If True, enables progress reporting using :mod:`tqdm`. Defaults to False.
|
|
238
|
+
**tqdm_kwargs: Additional keyword arguments for :mod:`tqdm` if progress reporting is enabled.
|
|
239
|
+
"""
|
|
240
|
+
for fut in as_completed(
|
|
241
|
+
futs,
|
|
242
|
+
timeout=timeout,
|
|
243
|
+
return_exceptions=return_exceptions,
|
|
244
|
+
tqdm=tqdm,
|
|
245
|
+
**tqdm_kwargs
|
|
246
|
+
):
|
|
131
247
|
yield await fut
|
|
132
248
|
|
|
249
|
+
|
|
133
250
|
@overload
|
|
134
|
-
async def __mapping_wrap(
|
|
251
|
+
async def __mapping_wrap(
|
|
252
|
+
k: K, v: Awaitable[V], return_exceptions: Literal[True] = True
|
|
253
|
+
) -> Union[V, Exception]: ...
|
|
135
254
|
@overload
|
|
136
|
-
async def __mapping_wrap(
|
|
137
|
-
|
|
255
|
+
async def __mapping_wrap(
|
|
256
|
+
k: K, v: Awaitable[V], return_exceptions: Literal[False] = False
|
|
257
|
+
) -> V: ...
|
|
258
|
+
async def __mapping_wrap(
|
|
259
|
+
k: K, v: Awaitable[V], return_exceptions: bool = False
|
|
260
|
+
) -> Union[V, Exception]:
|
|
261
|
+
"""Wraps a key-value pair of awaitable to catch exceptions and return them with the key.
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
k: The key associated with the awaitable.
|
|
265
|
+
v: The awaitable to wrap.
|
|
266
|
+
return_exceptions: If True, exceptions are wrapped and returned as results instead of raising them. Defaults to False.
|
|
267
|
+
|
|
268
|
+
Returns:
|
|
269
|
+
A tuple of the key and the result of the awaitable or the exception if one is raised.
|
|
270
|
+
"""
|
|
138
271
|
try:
|
|
139
272
|
return k, await v
|
|
140
273
|
except Exception as e:
|
|
@@ -142,4 +275,5 @@ async def __mapping_wrap(k: K, v: Awaitable[V], return_exceptions: bool = False)
|
|
|
142
275
|
return k, e
|
|
143
276
|
raise
|
|
144
277
|
|
|
145
|
-
|
|
278
|
+
|
|
279
|
+
__all__ = ["as_completed", "as_completed_mapping"]
|