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.

Files changed (73) hide show
  1. a_sync/ENVIRONMENT_VARIABLES.py +37 -5
  2. a_sync/__init__.py +53 -12
  3. a_sync/_smart.py +231 -28
  4. a_sync/_typing.py +112 -15
  5. a_sync/a_sync/__init__.py +35 -10
  6. a_sync/a_sync/_descriptor.py +248 -38
  7. a_sync/a_sync/_flags.py +78 -9
  8. a_sync/a_sync/_helpers.py +46 -13
  9. a_sync/a_sync/_kwargs.py +33 -8
  10. a_sync/a_sync/_meta.py +149 -28
  11. a_sync/a_sync/abstract.py +150 -28
  12. a_sync/a_sync/base.py +34 -16
  13. a_sync/a_sync/config.py +85 -14
  14. a_sync/a_sync/decorator.py +441 -139
  15. a_sync/a_sync/function.py +709 -147
  16. a_sync/a_sync/method.py +437 -110
  17. a_sync/a_sync/modifiers/__init__.py +85 -5
  18. a_sync/a_sync/modifiers/cache/__init__.py +116 -17
  19. a_sync/a_sync/modifiers/cache/memory.py +130 -20
  20. a_sync/a_sync/modifiers/limiter.py +101 -22
  21. a_sync/a_sync/modifiers/manager.py +142 -16
  22. a_sync/a_sync/modifiers/semaphores.py +121 -15
  23. a_sync/a_sync/property.py +383 -82
  24. a_sync/a_sync/singleton.py +44 -19
  25. a_sync/aliases.py +0 -1
  26. a_sync/asyncio/__init__.py +140 -1
  27. a_sync/asyncio/as_completed.py +213 -79
  28. a_sync/asyncio/create_task.py +70 -20
  29. a_sync/asyncio/gather.py +125 -58
  30. a_sync/asyncio/utils.py +3 -3
  31. a_sync/exceptions.py +248 -26
  32. a_sync/executor.py +164 -69
  33. a_sync/future.py +1227 -168
  34. a_sync/iter.py +173 -56
  35. a_sync/primitives/__init__.py +14 -2
  36. a_sync/primitives/_debug.py +72 -18
  37. a_sync/primitives/_loggable.py +41 -10
  38. a_sync/primitives/locks/__init__.py +5 -2
  39. a_sync/primitives/locks/counter.py +107 -38
  40. a_sync/primitives/locks/event.py +21 -7
  41. a_sync/primitives/locks/prio_semaphore.py +262 -63
  42. a_sync/primitives/locks/semaphore.py +138 -89
  43. a_sync/primitives/queue.py +601 -60
  44. a_sync/sphinx/__init__.py +0 -1
  45. a_sync/sphinx/ext.py +160 -50
  46. a_sync/task.py +313 -112
  47. a_sync/utils/__init__.py +12 -6
  48. a_sync/utils/iterators.py +170 -50
  49. {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/METADATA +1 -1
  50. ez_a_sync-0.22.16.dist-info/RECORD +74 -0
  51. {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/WHEEL +1 -1
  52. tests/conftest.py +1 -2
  53. tests/executor.py +250 -9
  54. tests/fixtures.py +61 -32
  55. tests/test_abstract.py +22 -4
  56. tests/test_as_completed.py +54 -21
  57. tests/test_base.py +264 -19
  58. tests/test_cache.py +31 -15
  59. tests/test_decorator.py +54 -28
  60. tests/test_executor.py +31 -13
  61. tests/test_future.py +45 -8
  62. tests/test_gather.py +8 -2
  63. tests/test_helpers.py +2 -0
  64. tests/test_iter.py +55 -13
  65. tests/test_limiter.py +5 -3
  66. tests/test_meta.py +23 -9
  67. tests/test_modified.py +4 -1
  68. tests/test_semaphore.py +15 -8
  69. tests/test_singleton.py +28 -11
  70. tests/test_task.py +162 -36
  71. ez_a_sync-0.22.14.dist-info/RECORD +0 -74
  72. {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/LICENSE.txt +0 -0
  73. {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/top_level.txt +0 -0
@@ -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
- class MyAsyncSingleton(ASyncGenericSingleton):
21
- @a_sync
22
- def my_method(self):
23
- # Method implementation
24
-
25
- # These will return the same synchronous instance
26
- sync_instance1 = MyAsyncSingleton(sync=True)
27
- sync_instance2 = MyAsyncSingleton(sync=True)
28
-
29
- # These will return the same asynchronous instance
30
- async_instance1 = MyAsyncSingleton(asynchronous=True)
31
- async_instance2 = MyAsyncSingleton(asynchronous=True)
32
-
33
- assert sync_instance1 is sync_instance2
34
- assert async_instance1 is async_instance2
35
- assert sync_instance1 is not async_instance1
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
@@ -1,4 +1,3 @@
1
-
2
1
  from a_sync.a_sync.modifiers.semaphores import dummy_semaphore as dummy
3
2
  from a_sync.a_sync.property import a_sync_cached_property as cached_property
4
3
  from a_sync.a_sync.property import a_sync_property as property
@@ -1,5 +1,17 @@
1
1
  """
2
- This package contains buffed versions of the objects found in the builtin `asyncio` 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
+ """
@@ -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(fs: Iterable[Awaitable[T]], *, timeout: Optional[float] = None, return_exceptions: bool = False, aiter: Literal[False] = False, tqdm: bool = False, **tqdm_kwargs: Any) -> Iterator[Coroutine[Any, Any, T]]:
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(fs: Iterable[Awaitable[T]], *, timeout: Optional[float] = None, return_exceptions: bool = False, aiter: Literal[True] = True, tqdm: bool = False, **tqdm_kwargs: Any) -> ASyncIterator[T]:
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(fs: Mapping[K, Awaitable[V]], *, timeout: Optional[float] = None, return_exceptions: bool = False, aiter: Literal[False] = False, tqdm: bool = False, **tqdm_kwargs: Any) -> Iterator[Coroutine[Any, Any, Tuple[K, V]]]:
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(fs: Mapping[K, Awaitable[V]], *, timeout: Optional[float] = None, return_exceptions: bool = False, aiter: Literal[True] = True, tqdm: bool = False, **tqdm_kwargs: Any) -> ASyncIterator[Tuple[K, V]]:
28
- ...
29
- def as_completed(fs, *, timeout: Optional[float] = None, return_exceptions: bool = False, aiter: bool = False, tqdm: bool = False, **tqdm_kwargs: Any):
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, providing additional features for mixed use cases of individual awaitable objects and mappings of awaitables.
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. Example below.
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
- Args:
42
- fs (Iterable[Awaitable[T] or Mapping[K, Awaitable[V]]]): The awaitables to await concurrently. It can be a list of individual awaitables or a mapping of awaitables.
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
- Returns:
50
- Iterator[Coroutine[Any, Any, T] or ASyncIterator[Tuple[K, V]]]: An iterator of results when awaiting individual awaitables or an async iterator when awaiting mappings.
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
- val = await coro
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
- for coro in as_completed(mapping):
69
- k, v = await coro
70
- ...
71
-
72
- async for k, v in as_completed(mapping, aiter=True):
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(fs, timeout=timeout, return_exceptions=return_exceptions, aiter=aiter, tqdm=tqdm, **tqdm_kwargs)
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(__yield_as_completed(fs, timeout=timeout, tqdm=tqdm, **tqdm_kwargs)) if aiter
82
- else tqdm_asyncio.as_completed(fs, timeout=timeout, **tqdm_kwargs) if tqdm
83
- else asyncio.as_completed(fs, timeout=timeout)
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(mapping: Mapping[K, Awaitable[V]], *, timeout: Optional[float] = None, return_exceptions: bool = False, aiter: Literal[True] = True, tqdm: bool = False, **tqdm_kwargs: Any) -> ASyncIterator[Tuple[K, V]]:
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(mapping: Mapping[K, Awaitable[V]], *, timeout: Optional[float] = None, return_exceptions: bool = False, aiter: Literal[False] = False, tqdm: bool = False, **tqdm_kwargs: Any) -> Iterator[Coroutine[Any, Any, Tuple[K, V]]]:
91
- ...
92
- def as_completed_mapping(mapping: Mapping[K, Awaitable[V]], *, timeout: Optional[float] = None, return_exceptions: bool = False, aiter: bool = False, tqdm: bool = False, **tqdm_kwargs: Any) -> Union[Iterator[Coroutine[Any, Any, Tuple[K, V]]], ASyncIterator[Tuple[K, V]]]:
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 (Mapping[K, Awaitable[V]]): A dictionary-like object where keys are of type K and values are awaitable objects of type V.
100
- timeout (float, optional): The maximum time, in seconds, to wait for the completion of awaitables. Defaults to None (no timeout).
101
- return_exceptions (bool, optional): If True, exceptions are returned as results instead of raising them. Defaults to False.
102
- aiter (bool, optional): If True, returns an async iterator of results. Defaults to False.
103
- tqdm (bool, optional): If True, enables progress reporting using tqdm. Defaults to False.
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
- mapping = {'key1': async_function1(), 'key2': async_function2()}
112
-
113
- for coro in as_completed_mapping(mapping):
114
- k, v = await coro
115
- ...
116
-
117
- async for k, v in as_completed_mapping(mapping, aiter=True):
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([__mapping_wrap(k, v, return_exceptions=return_exceptions) for k, v in mapping.items()], timeout=timeout, aiter=aiter, tqdm=tqdm, **tqdm_kwargs)
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
- async def __yield_as_completed(futs: Iterable[Awaitable[T]], *, timeout: Optional[float] = None, return_exceptions: bool = False, tqdm: bool = False, **tqdm_kwargs: Any) -> AsyncIterator[T]:
130
- for fut in as_completed(futs, timeout=timeout, return_exceptions=return_exceptions, tqdm=tqdm, **tqdm_kwargs):
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(k: K, v: Awaitable[V], return_exceptions: Literal[True] = True) -> Union[V, Exception]:...
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(k: K, v: Awaitable[V], return_exceptions: Literal[False] = False) -> V:...
137
- async def __mapping_wrap(k: K, v: Awaitable[V], return_exceptions: bool = False) -> Union[V, Exception]:
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
- __all__ = ["as_completed", "as_completed_mapping"]
278
+
279
+ __all__ = ["as_completed", "as_completed_mapping"]