ez-a-sync 0.22.15__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 (49) hide show
  1. a_sync/ENVIRONMENT_VARIABLES.py +34 -3
  2. a_sync/__init__.py +32 -9
  3. a_sync/_smart.py +105 -6
  4. a_sync/_typing.py +56 -3
  5. a_sync/a_sync/_descriptor.py +174 -12
  6. a_sync/a_sync/_flags.py +64 -3
  7. a_sync/a_sync/_helpers.py +40 -8
  8. a_sync/a_sync/_kwargs.py +30 -6
  9. a_sync/a_sync/_meta.py +35 -6
  10. a_sync/a_sync/abstract.py +57 -9
  11. a_sync/a_sync/config.py +44 -7
  12. a_sync/a_sync/decorator.py +217 -37
  13. a_sync/a_sync/function.py +339 -47
  14. a_sync/a_sync/method.py +241 -52
  15. a_sync/a_sync/modifiers/__init__.py +39 -1
  16. a_sync/a_sync/modifiers/cache/__init__.py +75 -5
  17. a_sync/a_sync/modifiers/cache/memory.py +50 -6
  18. a_sync/a_sync/modifiers/limiter.py +55 -6
  19. a_sync/a_sync/modifiers/manager.py +46 -2
  20. a_sync/a_sync/modifiers/semaphores.py +84 -11
  21. a_sync/a_sync/singleton.py +43 -19
  22. a_sync/asyncio/__init__.py +137 -1
  23. a_sync/asyncio/as_completed.py +44 -38
  24. a_sync/asyncio/create_task.py +46 -10
  25. a_sync/asyncio/gather.py +72 -25
  26. a_sync/exceptions.py +178 -11
  27. a_sync/executor.py +51 -3
  28. a_sync/future.py +671 -29
  29. a_sync/iter.py +64 -7
  30. a_sync/primitives/_debug.py +59 -5
  31. a_sync/primitives/_loggable.py +36 -6
  32. a_sync/primitives/locks/counter.py +74 -7
  33. a_sync/primitives/locks/prio_semaphore.py +87 -8
  34. a_sync/primitives/locks/semaphore.py +68 -20
  35. a_sync/primitives/queue.py +65 -26
  36. a_sync/task.py +51 -15
  37. a_sync/utils/iterators.py +52 -16
  38. {ez_a_sync-0.22.15.dist-info → ez_a_sync-0.22.16.dist-info}/METADATA +1 -1
  39. ez_a_sync-0.22.16.dist-info/RECORD +74 -0
  40. {ez_a_sync-0.22.15.dist-info → ez_a_sync-0.22.16.dist-info}/WHEEL +1 -1
  41. tests/executor.py +150 -12
  42. tests/test_abstract.py +15 -0
  43. tests/test_base.py +198 -2
  44. tests/test_executor.py +23 -0
  45. tests/test_singleton.py +13 -1
  46. tests/test_task.py +45 -17
  47. ez_a_sync-0.22.15.dist-info/RECORD +0 -74
  48. {ez_a_sync-0.22.15.dist-info → ez_a_sync-0.22.16.dist-info}/LICENSE.txt +0 -0
  49. {ez_a_sync-0.22.15.dist-info → ez_a_sync-0.22.16.dist-info}/top_level.txt +0 -0
@@ -4,10 +4,41 @@ envs = EnvVarFactory("EZASYNC")
4
4
 
5
5
  # We have some envs here to help you debug your custom class implementations
6
6
 
7
- # If you're only interested in debugging a specific class, set this to the class name
8
7
  DEBUG_CLASS_NAME = envs.create_env("DEBUG_CLASS_NAME", str, default="", verbose=False)
8
+ """str: The name of the class to debug.
9
+
10
+ If you're only interested in debugging a specific class, set this to the class name.
11
+
12
+ Examples:
13
+ To debug a class named `MyClass`, set the environment variable:
14
+
15
+ .. code-block:: bash
16
+
17
+ export EZASYNC_DEBUG_CLASS_NAME=MyClass
18
+
19
+ See Also:
20
+ :func:`DEBUG_MODE` for enabling debug mode on all classes.
21
+ """
9
22
 
10
- # Set this to enable debug mode on all classes
11
23
  DEBUG_MODE = envs.create_env(
12
- "DEBUG_MODE", bool, default=DEBUG_CLASS_NAME, verbose=False
24
+ "DEBUG_MODE", bool, default=bool(DEBUG_CLASS_NAME), verbose=False
13
25
  )
26
+ """bool: Enables debug mode on all classes.
27
+
28
+ Set this environment variable to `True` to enable debug mode on all classes.
29
+ If `DEBUG_CLASS_NAME` is set to a truthy value other than an empty string,
30
+ `DEBUG_MODE` will default to `True`.
31
+
32
+ Examples:
33
+ To enable debug mode globally, set the environment variable:
34
+
35
+ .. code-block:: bash
36
+
37
+ export EZASYNC_DEBUG_MODE=True
38
+
39
+ If you have set `DEBUG_CLASS_NAME` to a specific class, `DEBUG_MODE` will
40
+ automatically be `True` unless `DEBUG_CLASS_NAME` is an empty string.
41
+
42
+ See Also:
43
+ :func:`DEBUG_CLASS_NAME` for debugging a specific class.
44
+ """
a_sync/__init__.py CHANGED
@@ -8,17 +8,40 @@ that can operate in both synchronous and asynchronous contexts. Additionally, it
8
8
  such as queues and locks, with extra functionality.
9
9
 
10
10
  Modules and components included:
11
- - `aliases`, `exceptions`, `iter`, `task`: Core modules of the library.
12
- - `ASyncGenericBase`, `ASyncGenericSingleton`, `a_sync`: Base classes and decorators for dual-context execution.
13
- - `apply_semaphore`: Function to apply semaphores to coroutines.
14
- - `ASyncCachedPropertyDescriptor`, `ASyncPropertyDescriptor`, `cached_property`, `property`: Property descriptors for async properties.
15
- - `as_completed`, `create_task`, `gather`: Enhanced asyncio functions.
16
- - Executors: `AsyncThreadPoolExecutor`, `AsyncProcessPoolExecutor`, `PruningThreadPoolExecutor` for async execution.
17
- - Iterators: `ASyncFilter`, `ASyncSorter`, `ASyncIterable`, `ASyncIterator` for async iteration.
18
- - Utilities: `all`, `any`, `as_yielded` for async utilities.
11
+ - :mod:`~aliases`, :mod:`~exceptions`, :mod:`~iter`, :mod:`~task`: Core modules of the library.
12
+ - :class:`~ASyncGenericBase`, :class:`~ASyncGenericSingleton`, :func:`~a_sync`: Base classes and decorators for dual-context execution.
13
+ - :class:`~ASyncCachedPropertyDescriptor`, :class:`~ASyncPropertyDescriptor`, `cached_property`, `property`: Property descriptors for async properties.
14
+ - :func:`~as_completed`, :func:`~create_task`, :func:`~gather`: Enhanced asyncio functions.
15
+ - Executors: :class:`~AsyncThreadPoolExecutor`, :class:`~AsyncProcessPoolExecutor`, :class:`~PruningThreadPoolExecutor` for async execution.
16
+ - Iterators: :class:`~ASyncFilter`, :class:`~ASyncSorter`, :class:`~ASyncIterable`, :class:`~ASyncIterator` for async iteration.
17
+ - Utilities: :func:`~all`, :func:`~any`, :func:`~as_yielded`, :func:`~exhaust_iterator`, :func:`~exhaust_iterators` for async utilities.
18
+ - :func:`~apply_semaphore`: Function to apply semaphores to coroutines.
19
19
 
20
20
  Alias for backward compatibility:
21
- - `ASyncBase` is an alias for `ASyncGenericBase`, which will be removed eventually, probably in version 0.1.0.
21
+ - :class:`~ASyncBase` is an alias for :class:`~ASyncGenericBase`, which will be removed eventually, probably in version 0.1.0.
22
+
23
+ Examples:
24
+ Using the `@a_sync` decorator:
25
+ >>> from a_sync import a_sync
26
+ >>> @a_sync
27
+ ... async def my_function():
28
+ ... return "Hello, World!"
29
+ >>> result = await my_function()
30
+ >>> print(result)
31
+
32
+ Using `ASyncGenericBase` for dual-context classes:
33
+ >>> from a_sync import ASyncGenericBase
34
+ >>> class MyClass(ASyncGenericBase):
35
+ ... async def my_method(self):
36
+ ... return "Hello from MyClass"
37
+ >>> obj = MyClass()
38
+ >>> result = await obj.my_method()
39
+ >>> print(result)
40
+
41
+ See Also:
42
+ - :mod:`a_sync.a_sync`: Contains the core classes and decorators.
43
+ - :mod:`a_sync.asyncio`: Provides enhanced asyncio functions.
44
+ - :mod:`a_sync.primitives`: Includes modified versions of standard asyncio primitives.
22
45
  """
23
46
 
24
47
  from a_sync import aliases, exceptions, iter, task
a_sync/_smart.py CHANGED
@@ -1,7 +1,8 @@
1
1
  """
2
2
  This module defines smart future and task utilities for the a_sync library.
3
3
  These utilities provide enhanced functionality for managing asynchronous tasks and futures,
4
- including task shielding and a custom task factory for creating SmartTask instances.
4
+ including a custom task factory for creating :class:`~SmartTask` instances and a shielding mechanism
5
+ to protect tasks from cancellation.
5
6
  """
6
7
 
7
8
  import asyncio
@@ -37,6 +38,27 @@ class _SmartFutureMixin(Generic[T]):
37
38
  def __await__(self: Union["SmartFuture", "SmartTask"]) -> Generator[Any, None, T]:
38
39
  """
39
40
  Await the smart future or task, handling waiters and logging.
41
+
42
+ Yields:
43
+ The result of the future or task.
44
+
45
+ Raises:
46
+ RuntimeError: If await wasn't used with future.
47
+
48
+ Example:
49
+ Awaiting a SmartFuture:
50
+
51
+ ```python
52
+ future = SmartFuture()
53
+ result = await future
54
+ ```
55
+
56
+ Awaiting a SmartTask:
57
+
58
+ ```python
59
+ task = SmartTask(coro=my_coroutine())
60
+ result = await task
61
+ ```
40
62
  """
41
63
  if self.done():
42
64
  return self.result() # May raise too.
@@ -54,6 +76,12 @@ class _SmartFutureMixin(Generic[T]):
54
76
  # NOTE: we check .done() because the callback may not have ran yet and its very lightweight
55
77
  """
56
78
  Get the number of waiters currently awaiting the future or task.
79
+
80
+ Example:
81
+ ```python
82
+ future = SmartFuture()
83
+ print(future.num_waiters)
84
+ ```
57
85
  """
58
86
  if self.done():
59
87
  # if there are any waiters left, there won't be once the event loop runs once
@@ -67,6 +95,9 @@ class _SmartFutureMixin(Generic[T]):
67
95
  Callback to clean up waiters when a waiter task is done.
68
96
 
69
97
  Removes the waiter from _waiters, and _queue._futs if applicable
98
+
99
+ Args:
100
+ waiter: The waiter task to clean up.
70
101
  """
71
102
  if not self.done():
72
103
  self._waiters.remove(waiter)
@@ -84,8 +115,16 @@ class SmartFuture(_SmartFutureMixin[T], asyncio.Future):
84
115
  """
85
116
  A smart future that tracks waiters and integrates with a smart processing queue.
86
117
 
87
- Inherits from both _SmartFutureMixin and asyncio.Future, providing additional functionality
118
+ Inherits from both :class:`_SmartFutureMixin` and :class:`asyncio.Future`, providing additional functionality
88
119
  for tracking waiters and integrating with a smart processing queue.
120
+
121
+ Example:
122
+ Creating and awaiting a SmartFuture:
123
+
124
+ ```python
125
+ future = SmartFuture()
126
+ await future
127
+ ```
89
128
  """
90
129
 
91
130
  _queue = None
@@ -105,6 +144,11 @@ class SmartFuture(_SmartFutureMixin[T], asyncio.Future):
105
144
  queue: Optional; a smart processing queue.
106
145
  key: Optional; a key identifying the future.
107
146
  loop: Optional; the event loop.
147
+
148
+ Example:
149
+ ```python
150
+ future = SmartFuture(queue=my_queue, key=my_key)
151
+ ```
108
152
  """
109
153
  super().__init__(loop=loop)
110
154
  if queue:
@@ -125,8 +169,12 @@ class SmartFuture(_SmartFutureMixin[T], asyncio.Future):
125
169
  Args:
126
170
  other: Another SmartFuture to compare with.
127
171
 
128
- Returns:
129
- True if self has more waiters than other.
172
+ Example:
173
+ ```python
174
+ future1 = SmartFuture()
175
+ future2 = SmartFuture()
176
+ print(future1 < future2)
177
+ ```
130
178
  """
131
179
  return self.num_waiters > other.num_waiters
132
180
 
@@ -138,7 +186,7 @@ def create_future(
138
186
  loop: Optional[asyncio.AbstractEventLoop] = None,
139
187
  ) -> SmartFuture[V]:
140
188
  """
141
- Create a SmartFuture instance.
189
+ Create a :class:`~SmartFuture` instance.
142
190
 
143
191
  Args:
144
192
  queue: Optional; a smart processing queue.
@@ -147,6 +195,13 @@ def create_future(
147
195
 
148
196
  Returns:
149
197
  A SmartFuture instance.
198
+
199
+ Example:
200
+ Creating a SmartFuture using the factory function:
201
+
202
+ ```python
203
+ future = create_future(queue=my_queue, key=my_key)
204
+ ```
150
205
  """
151
206
  return SmartFuture(queue=queue, key=key, loop=loop or asyncio.get_event_loop())
152
207
 
@@ -155,8 +210,16 @@ class SmartTask(_SmartFutureMixin[T], asyncio.Task):
155
210
  """
156
211
  A smart task that tracks waiters and integrates with a smart processing queue.
157
212
 
158
- Inherits from both _SmartFutureMixin and asyncio.Task, providing additional functionality
213
+ Inherits from both :class:`_SmartFutureMixin` and :class:`asyncio.Task`, providing additional functionality
159
214
  for tracking waiters and integrating with a smart processing queue.
215
+
216
+ Example:
217
+ Creating and awaiting a SmartTask:
218
+
219
+ ```python
220
+ task = SmartTask(coro=my_coroutine())
221
+ await task
222
+ ```
160
223
  """
161
224
 
162
225
  def __init__(
@@ -173,6 +236,11 @@ class SmartTask(_SmartFutureMixin[T], asyncio.Task):
173
236
  coro: The coroutine to run in the task.
174
237
  loop: Optional; the event loop.
175
238
  name: Optional; the name of the task.
239
+
240
+ Example:
241
+ ```python
242
+ task = SmartTask(coro=my_coroutine(), name="my_task")
243
+ ```
176
244
  """
177
245
  super().__init__(coro, loop=loop, name=name)
178
246
  self._waiters: Set["asyncio.Task[T]"] = set()
@@ -193,6 +261,17 @@ def smart_task_factory(
193
261
 
194
262
  Returns:
195
263
  A SmartTask instance running the provided coroutine.
264
+
265
+ Example:
266
+ Using the smart task factory to create a SmartTask:
267
+
268
+ ```python
269
+ loop = asyncio.get_event_loop()
270
+ task = smart_task_factory(loop, my_coroutine())
271
+ ```
272
+
273
+ See Also:
274
+ - :func:`set_smart_task_factory`
196
275
  """
197
276
  return SmartTask(coro, loop=loop)
198
277
 
@@ -203,6 +282,16 @@ def set_smart_task_factory(loop: asyncio.AbstractEventLoop = None) -> None:
203
282
 
204
283
  Args:
205
284
  loop: Optional; the event loop. If None, the current event loop is used.
285
+
286
+ Example:
287
+ Setting the smart task factory for the current event loop:
288
+
289
+ ```python
290
+ set_smart_task_factory()
291
+ ```
292
+
293
+ See Also:
294
+ - :func:`smart_task_factory`
206
295
  """
207
296
  if loop is None:
208
297
  loop = a_sync.asyncio.get_event_loop()
@@ -241,6 +330,16 @@ def shield(
241
330
  Args:
242
331
  arg: The awaitable to shield from cancellation.
243
332
  loop: Optional; the event loop. Deprecated since Python 3.8.
333
+
334
+ Example:
335
+ Using shield to protect a coroutine from cancellation:
336
+
337
+ ```python
338
+ result = await shield(my_coroutine())
339
+ ```
340
+
341
+ See Also:
342
+ - :func:`asyncio.shield`
244
343
  """
245
344
  if loop is not None:
246
345
  warnings.warn(
a_sync/_typing.py CHANGED
@@ -1,7 +1,60 @@
1
1
  """
2
- This module provides type definitions and type-related utilities for the a_sync library.
3
- It includes various type aliases, protocols, and TypedDicts used throughout the library
4
- to enhance type checking and provide better IDE support.
2
+ This module provides type definitions and type-related utilities for the `a_sync` library.
3
+
4
+ It includes various type aliases and protocols used throughout the library to enhance type checking and provide better IDE support.
5
+
6
+ Examples:
7
+ The following examples demonstrate how to use some of the type aliases and protocols defined in this module.
8
+
9
+ Example of a function that can return either an awaitable or a direct value:
10
+
11
+ ```python
12
+ from a_sync._typing import MaybeAwaitable
13
+ from typing import Awaitable
14
+
15
+ async def process_data(data: MaybeAwaitable[int]) -> int:
16
+ if isinstance(data, Awaitable):
17
+ return await data
18
+ return data
19
+
20
+ # Usage
21
+ import asyncio
22
+
23
+ async def main():
24
+ result = await process_data(asyncio.sleep(1, result=42))
25
+ print(result) # Output: 42
26
+
27
+ result = await process_data(42)
28
+ print(result) # Output: 42
29
+
30
+ asyncio.run(main())
31
+ ```
32
+
33
+ Example of defining a coroutine function type:
34
+
35
+ ```python
36
+ from a_sync._typing import CoroFn
37
+
38
+ async def async_function(x: int) -> str:
39
+ return str(x)
40
+
41
+ coro_fn: CoroFn[[int], str] = async_function
42
+ ```
43
+
44
+ Example of defining a synchronous function type:
45
+
46
+ ```python
47
+ from a_sync._typing import SyncFn
48
+
49
+ def sync_function(x: int) -> str:
50
+ return str(x)
51
+
52
+ sync_fn: SyncFn[[int], str] = sync_function
53
+ ```
54
+
55
+ See Also:
56
+ - :mod:`typing`
57
+ - :mod:`asyncio`
5
58
  """
6
59
 
7
60
  import asyncio
@@ -1,8 +1,14 @@
1
1
  """
2
- This module contains the ASyncDescriptor class, which is used to create sync/async methods
2
+ This module contains the :class:`ASyncDescriptor` class, which is used to create dual-function sync/async methods
3
3
  and properties.
4
4
 
5
- It also includes utility methods for mapping operations across multiple instances.
5
+ The :class:`ASyncDescriptor` class provides functionality for mapping operations across multiple instances
6
+ and includes utility methods for common operations such as checking if all or any results are truthy,
7
+ and finding the minimum, maximum, or sum of results of the method or property mapped across multiple instances.
8
+
9
+ See Also:
10
+ - :class:`~a_sync.a_sync.function.ASyncFunction`
11
+ - :class:`~a_sync.a_sync.method.ASyncMethodDescriptor`
6
12
  """
7
13
 
8
14
  import functools
@@ -23,6 +29,27 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
23
29
  and includes utility methods for common operations such as checking if all or any
24
30
  results are truthy, and finding the minimum, maximum, or sum of results of the method
25
31
  or property mapped across multiple instances.
32
+
33
+ Examples:
34
+ To create a dual-function method or property, subclass :class:`ASyncDescriptor` and implement
35
+ the desired functionality. You can then use the provided utility methods to perform operations
36
+ across multiple instances.
37
+
38
+ ```python
39
+ class MyDescriptor(ASyncDescriptor):
40
+ def __init__(self, func):
41
+ super().__init__(func)
42
+
43
+ class MyClass:
44
+ my_method = MyDescriptor(lambda x: x * 2)
45
+
46
+ instance = MyClass()
47
+ result = instance.my_method.map([1, 2, 3])
48
+ ```
49
+
50
+ See Also:
51
+ - :class:`~a_sync.a_sync.function.ASyncFunction`
52
+ - :class:`~a_sync.a_sync.method.ASyncMethodDescriptor`
26
53
  """
27
54
 
28
55
  __wrapped__: AnyFn[Concatenate[I, P], T]
@@ -37,7 +64,7 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
37
64
  **modifiers: ModifierKwargs,
38
65
  ) -> None:
39
66
  """
40
- Initialize the {cls}.
67
+ Initialize the :class:`ASyncDescriptor`.
41
68
 
42
69
  Args:
43
70
  _fget: The function to be wrapped.
@@ -61,7 +88,7 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
61
88
  self.__wrapped__ = _fget
62
89
 
63
90
  self.field_name = field_name or _fget.__name__
64
- """The name of the field the {cls} is bound to."""
91
+ """The name of the field the :class:`ASyncDescriptor` is bound to."""
65
92
 
66
93
  functools.update_wrapper(self, self.__wrapped__)
67
94
 
@@ -70,7 +97,7 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
70
97
 
71
98
  def __set_name__(self, owner, name):
72
99
  """
73
- Set the field name when the {cls} is assigned to a class.
100
+ Set the field name when the :class:`ASyncDescriptor` is assigned to a class.
74
101
 
75
102
  Args:
76
103
  owner: The class owning this descriptor.
@@ -82,14 +109,25 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
82
109
  self, *instances: AnyIterable[I], **bound_method_kwargs: P.kwargs
83
110
  ) -> "TaskMapping[I, T]":
84
111
  """
85
- Create a TaskMapping for the given instances.
112
+ Create a :class:`TaskMapping` for the given instances.
86
113
 
87
114
  Args:
88
115
  *instances: Iterable of instances to map over.
89
116
  **bound_method_kwargs: Additional keyword arguments for the bound method.
90
117
 
91
118
  Returns:
92
- A TaskMapping object.
119
+ A :class:`TaskMapping` object.
120
+
121
+ Examples:
122
+ class MyDescriptor(ASyncDescriptor):
123
+ def __init__(self, func):
124
+ super().__init__(func)
125
+
126
+ class MyClass:
127
+ my_method = MyDescriptor(lambda x: x * 2)
128
+
129
+ instance = MyClass()
130
+ result = instance.my_method.map([1, 2, 3])
93
131
  """
94
132
  from a_sync.task import TaskMapping
95
133
 
@@ -101,7 +139,18 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
101
139
  Create an :class:`~ASyncFunction` that checks if all results are truthy.
102
140
 
103
141
  Returns:
104
- An ASyncFunction object.
142
+ An :class:`ASyncFunction` object.
143
+
144
+ Examples:
145
+ class MyDescriptor(ASyncDescriptor):
146
+ def __init__(self, func):
147
+ super().__init__(func)
148
+
149
+ class MyClass:
150
+ my_method = MyDescriptor(lambda x: x > 0)
151
+
152
+ instance = MyClass()
153
+ result = await instance.my_method.all([1, 2, 3])
105
154
  """
106
155
  return decorator.a_sync(default=self.default)(self._all)
107
156
 
@@ -111,7 +160,18 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
111
160
  Create an :class:`~ASyncFunction` that checks if any result is truthy.
112
161
 
113
162
  Returns:
114
- An ASyncFunction object.
163
+ An :class:`ASyncFunction` object.
164
+
165
+ Examples:
166
+ class MyDescriptor(ASyncDescriptor):
167
+ def __init__(self, func):
168
+ super().__init__(func)
169
+
170
+ class MyClass:
171
+ my_method = MyDescriptor(lambda x: x > 0)
172
+
173
+ instance = MyClass()
174
+ result = await instance.my_method.any([-1, 0, 1])
115
175
  """
116
176
  return decorator.a_sync(default=self.default)(self._any)
117
177
 
@@ -121,7 +181,20 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
121
181
  Create an :class:`~ASyncFunction` that returns the minimum result.
122
182
 
123
183
  Returns:
124
- An ASyncFunction object.
184
+ An :class:`ASyncFunction` object.
185
+
186
+ Examples:
187
+ ```python
188
+ class MyDescriptor(ASyncDescriptor):
189
+ def __init__(self, func):
190
+ super().__init__(func)
191
+
192
+ class MyClass:
193
+ my_method = MyDescriptor(lambda x: x)
194
+
195
+ instance = MyClass()
196
+ result = await instance.my_method.min([3, 1, 2])
197
+ ```
125
198
  """
126
199
  return decorator.a_sync(default=self.default)(self._min)
127
200
 
@@ -131,7 +204,18 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
131
204
  Create an :class:`~ASyncFunction` that returns the maximum result.
132
205
 
133
206
  Returns:
134
- An ASyncFunction object.
207
+ An :class:`ASyncFunction` object.
208
+
209
+ Examples:
210
+ class MyDescriptor(ASyncDescriptor):
211
+ def __init__(self, func):
212
+ super().__init__(func)
213
+
214
+ class MyClass:
215
+ my_method = MyDescriptor(lambda x: x)
216
+
217
+ instance = MyClass()
218
+ result = await instance.my_method.max([3, 1, 2])
135
219
  """
136
220
  return decorator.a_sync(default=self.default)(self._max)
137
221
 
@@ -141,7 +225,20 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
141
225
  Create an :class:`~ASyncFunction` that returns the sum of results.
142
226
 
143
227
  Returns:
144
- An ASyncFunction object.
228
+ An :class:`ASyncFunction` object.
229
+
230
+ Examples:
231
+ ```python
232
+ class MyDescriptor(ASyncDescriptor):
233
+ def __init__(self, func):
234
+ super().__init__(func)
235
+
236
+ class MyClass:
237
+ my_method = MyDescriptor(lambda x: x)
238
+
239
+ instance = MyClass()
240
+ result = await instance.my_method.sum([1, 2, 3])
241
+ ```
145
242
  """
146
243
  return decorator.a_sync(default=self.default)(self._sum)
147
244
 
@@ -163,6 +260,19 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
163
260
 
164
261
  Returns:
165
262
  A boolean indicating if all results are truthy.
263
+
264
+ Examples:
265
+ ```python
266
+ class MyDescriptor(ASyncDescriptor):
267
+ def __init__(self, func):
268
+ super().__init__(func)
269
+
270
+ class MyClass:
271
+ my_method = MyDescriptor(lambda x: x > 0)
272
+
273
+ instance = MyClass()
274
+ result = await instance.my_method._all([1, 2, 3])
275
+ ```
166
276
  """
167
277
  return await self.map(
168
278
  *instances, concurrency=concurrency, name=name, **kwargs
@@ -186,6 +296,19 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
186
296
 
187
297
  Returns:
188
298
  A boolean indicating if any result is truthy.
299
+
300
+ Examples:
301
+ ```python
302
+ class MyDescriptor(ASyncDescriptor):
303
+ def __init__(self, func):
304
+ super().__init__(func)
305
+
306
+ class MyClass:
307
+ my_method = MyDescriptor(lambda x: x > 0)
308
+
309
+ instance = MyClass()
310
+ result = await instance.my_method._any([-1, 0, 1])
311
+ ```
189
312
  """
190
313
  return await self.map(
191
314
  *instances, concurrency=concurrency, name=name, **kwargs
@@ -209,6 +332,19 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
209
332
 
210
333
  Returns:
211
334
  The minimum result.
335
+
336
+ Examples:
337
+ ```python
338
+ class MyDescriptor(ASyncDescriptor):
339
+ def __init__(self, func):
340
+ super().__init__(func)
341
+
342
+ class MyClass:
343
+ my_method = MyDescriptor(lambda x: x)
344
+
345
+ instance = MyClass()
346
+ result = await instance.my_method._min([3, 1, 2])
347
+ ```
212
348
  """
213
349
  return await self.map(
214
350
  *instances, concurrency=concurrency, name=name, **kwargs
@@ -232,6 +368,19 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
232
368
 
233
369
  Returns:
234
370
  The maximum result.
371
+
372
+ Examples:
373
+ ```python
374
+ class MyDescriptor(ASyncDescriptor):
375
+ def __init__(self, func):
376
+ super().__init__(func)
377
+
378
+ class MyClass:
379
+ my_method = MyDescriptor(lambda x: x)
380
+
381
+ instance = MyClass()
382
+ result = await instance.my_method._max([3, 1, 2])
383
+ ```
235
384
  """
236
385
  return await self.map(
237
386
  *instances, concurrency=concurrency, name=name, **kwargs
@@ -255,6 +404,19 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
255
404
 
256
405
  Returns:
257
406
  The sum of the results.
407
+
408
+ Examples:
409
+ ```python
410
+ class MyDescriptor(ASyncDescriptor):
411
+ def __init__(self, func):
412
+ super().__init__(func)
413
+
414
+ class MyClass:
415
+ my_method = MyDescriptor(lambda x: x)
416
+
417
+ instance = MyClass()
418
+ result = await instance.my_method._sum([1, 2, 3])
419
+ ```
258
420
  """
259
421
  return await self.map(
260
422
  *instances, concurrency=concurrency, name=name, **kwargs