ez-a-sync 0.33.4__cp313-cp313-musllinux_1_2_i686.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.
Files changed (177) hide show
  1. a_sync/ENVIRONMENT_VARIABLES.py +42 -0
  2. a_sync/__init__.pxd +2 -0
  3. a_sync/__init__.py +145 -0
  4. a_sync/_smart.c +22830 -0
  5. a_sync/_smart.cpython-313-i386-linux-musl.so +0 -0
  6. a_sync/_smart.pxd +2 -0
  7. a_sync/_smart.pyi +202 -0
  8. a_sync/_smart.pyx +674 -0
  9. a_sync/_typing.py +258 -0
  10. a_sync/a_sync/__init__.py +60 -0
  11. a_sync/a_sync/_descriptor.c +20537 -0
  12. a_sync/a_sync/_descriptor.cpython-313-i386-linux-musl.so +0 -0
  13. a_sync/a_sync/_descriptor.pyi +33 -0
  14. a_sync/a_sync/_descriptor.pyx +422 -0
  15. a_sync/a_sync/_flags.c +6082 -0
  16. a_sync/a_sync/_flags.cpython-313-i386-linux-musl.so +0 -0
  17. a_sync/a_sync/_flags.pxd +3 -0
  18. a_sync/a_sync/_flags.pyx +92 -0
  19. a_sync/a_sync/_helpers.c +14529 -0
  20. a_sync/a_sync/_helpers.cpython-313-i386-linux-musl.so +0 -0
  21. a_sync/a_sync/_helpers.pxd +3 -0
  22. a_sync/a_sync/_helpers.pyi +10 -0
  23. a_sync/a_sync/_helpers.pyx +167 -0
  24. a_sync/a_sync/_kwargs.c +12202 -0
  25. a_sync/a_sync/_kwargs.cpython-313-i386-linux-musl.so +0 -0
  26. a_sync/a_sync/_kwargs.pxd +2 -0
  27. a_sync/a_sync/_kwargs.pyx +64 -0
  28. a_sync/a_sync/_meta.py +210 -0
  29. a_sync/a_sync/abstract.c +12420 -0
  30. a_sync/a_sync/abstract.cpython-313-i386-linux-musl.so +0 -0
  31. a_sync/a_sync/abstract.pyi +141 -0
  32. a_sync/a_sync/abstract.pyx +221 -0
  33. a_sync/a_sync/base.c +14940 -0
  34. a_sync/a_sync/base.cpython-313-i386-linux-musl.so +0 -0
  35. a_sync/a_sync/base.pyi +60 -0
  36. a_sync/a_sync/base.pyx +271 -0
  37. a_sync/a_sync/config.py +168 -0
  38. a_sync/a_sync/decorator.py +651 -0
  39. a_sync/a_sync/flags.c +5272 -0
  40. a_sync/a_sync/flags.cpython-313-i386-linux-musl.so +0 -0
  41. a_sync/a_sync/flags.pxd +72 -0
  42. a_sync/a_sync/flags.pyi +74 -0
  43. a_sync/a_sync/flags.pyx +72 -0
  44. a_sync/a_sync/function.c +37856 -0
  45. a_sync/a_sync/function.cpython-313-i386-linux-musl.so +0 -0
  46. a_sync/a_sync/function.pxd +28 -0
  47. a_sync/a_sync/function.pyi +571 -0
  48. a_sync/a_sync/function.pyx +1381 -0
  49. a_sync/a_sync/method.c +29662 -0
  50. a_sync/a_sync/method.cpython-313-i386-linux-musl.so +0 -0
  51. a_sync/a_sync/method.pxd +9 -0
  52. a_sync/a_sync/method.pyi +523 -0
  53. a_sync/a_sync/method.pyx +1023 -0
  54. a_sync/a_sync/modifiers/__init__.pxd +1 -0
  55. a_sync/a_sync/modifiers/__init__.py +101 -0
  56. a_sync/a_sync/modifiers/cache/__init__.py +160 -0
  57. a_sync/a_sync/modifiers/cache/memory.py +165 -0
  58. a_sync/a_sync/modifiers/limiter.py +132 -0
  59. a_sync/a_sync/modifiers/manager.c +16157 -0
  60. a_sync/a_sync/modifiers/manager.cpython-313-i386-linux-musl.so +0 -0
  61. a_sync/a_sync/modifiers/manager.pxd +5 -0
  62. a_sync/a_sync/modifiers/manager.pyi +219 -0
  63. a_sync/a_sync/modifiers/manager.pyx +299 -0
  64. a_sync/a_sync/modifiers/semaphores.py +173 -0
  65. a_sync/a_sync/property.c +27268 -0
  66. a_sync/a_sync/property.cpython-313-i386-linux-musl.so +0 -0
  67. a_sync/a_sync/property.pyi +376 -0
  68. a_sync/a_sync/property.pyx +819 -0
  69. a_sync/a_sync/singleton.py +63 -0
  70. a_sync/aliases.py +3 -0
  71. a_sync/async_property/__init__.pxd +1 -0
  72. a_sync/async_property/__init__.py +1 -0
  73. a_sync/async_property/cached.c +20397 -0
  74. a_sync/async_property/cached.cpython-313-i386-linux-musl.so +0 -0
  75. a_sync/async_property/cached.pxd +10 -0
  76. a_sync/async_property/cached.pyi +45 -0
  77. a_sync/async_property/cached.pyx +178 -0
  78. a_sync/async_property/proxy.c +34662 -0
  79. a_sync/async_property/proxy.cpython-313-i386-linux-musl.so +0 -0
  80. a_sync/async_property/proxy.pxd +2 -0
  81. a_sync/async_property/proxy.pyi +124 -0
  82. a_sync/async_property/proxy.pyx +474 -0
  83. a_sync/asyncio/__init__.pxd +6 -0
  84. a_sync/asyncio/__init__.py +164 -0
  85. a_sync/asyncio/as_completed.c +18849 -0
  86. a_sync/asyncio/as_completed.cpython-313-i386-linux-musl.so +0 -0
  87. a_sync/asyncio/as_completed.pxd +8 -0
  88. a_sync/asyncio/as_completed.pyi +109 -0
  89. a_sync/asyncio/as_completed.pyx +269 -0
  90. a_sync/asyncio/create_task.c +15912 -0
  91. a_sync/asyncio/create_task.cpython-313-i386-linux-musl.so +0 -0
  92. a_sync/asyncio/create_task.pxd +2 -0
  93. a_sync/asyncio/create_task.pyi +51 -0
  94. a_sync/asyncio/create_task.pyx +271 -0
  95. a_sync/asyncio/gather.c +16687 -0
  96. a_sync/asyncio/gather.cpython-313-i386-linux-musl.so +0 -0
  97. a_sync/asyncio/gather.pyi +107 -0
  98. a_sync/asyncio/gather.pyx +218 -0
  99. a_sync/asyncio/igather.c +13080 -0
  100. a_sync/asyncio/igather.cpython-313-i386-linux-musl.so +0 -0
  101. a_sync/asyncio/igather.pxd +1 -0
  102. a_sync/asyncio/igather.pyi +8 -0
  103. a_sync/asyncio/igather.pyx +183 -0
  104. a_sync/asyncio/sleep.c +9601 -0
  105. a_sync/asyncio/sleep.cpython-313-i386-linux-musl.so +0 -0
  106. a_sync/asyncio/sleep.pyi +14 -0
  107. a_sync/asyncio/sleep.pyx +49 -0
  108. a_sync/debugging.c +15370 -0
  109. a_sync/debugging.cpython-313-i386-linux-musl.so +0 -0
  110. a_sync/debugging.pyi +76 -0
  111. a_sync/debugging.pyx +107 -0
  112. a_sync/exceptions.c +13320 -0
  113. a_sync/exceptions.cpython-313-i386-linux-musl.so +0 -0
  114. a_sync/exceptions.pyi +376 -0
  115. a_sync/exceptions.pyx +446 -0
  116. a_sync/executor.py +619 -0
  117. a_sync/functools.c +12746 -0
  118. a_sync/functools.cpython-313-i386-linux-musl.so +0 -0
  119. a_sync/functools.pxd +7 -0
  120. a_sync/functools.pyi +33 -0
  121. a_sync/functools.pyx +139 -0
  122. a_sync/future.py +1497 -0
  123. a_sync/iter.c +37279 -0
  124. a_sync/iter.cpython-313-i386-linux-musl.so +0 -0
  125. a_sync/iter.pxd +11 -0
  126. a_sync/iter.pyi +370 -0
  127. a_sync/iter.pyx +981 -0
  128. a_sync/primitives/__init__.pxd +1 -0
  129. a_sync/primitives/__init__.py +53 -0
  130. a_sync/primitives/_debug.c +15765 -0
  131. a_sync/primitives/_debug.cpython-313-i386-linux-musl.so +0 -0
  132. a_sync/primitives/_debug.pxd +12 -0
  133. a_sync/primitives/_debug.pyi +52 -0
  134. a_sync/primitives/_debug.pyx +223 -0
  135. a_sync/primitives/_loggable.c +11538 -0
  136. a_sync/primitives/_loggable.cpython-313-i386-linux-musl.so +0 -0
  137. a_sync/primitives/_loggable.pxd +4 -0
  138. a_sync/primitives/_loggable.pyi +66 -0
  139. a_sync/primitives/_loggable.pyx +102 -0
  140. a_sync/primitives/locks/__init__.pxd +8 -0
  141. a_sync/primitives/locks/__init__.py +17 -0
  142. a_sync/primitives/locks/counter.c +17938 -0
  143. a_sync/primitives/locks/counter.cpython-313-i386-linux-musl.so +0 -0
  144. a_sync/primitives/locks/counter.pxd +12 -0
  145. a_sync/primitives/locks/counter.pyi +151 -0
  146. a_sync/primitives/locks/counter.pyx +267 -0
  147. a_sync/primitives/locks/event.c +17072 -0
  148. a_sync/primitives/locks/event.cpython-313-i386-linux-musl.so +0 -0
  149. a_sync/primitives/locks/event.pxd +22 -0
  150. a_sync/primitives/locks/event.pyi +43 -0
  151. a_sync/primitives/locks/event.pyx +185 -0
  152. a_sync/primitives/locks/prio_semaphore.c +25635 -0
  153. a_sync/primitives/locks/prio_semaphore.cpython-313-i386-linux-musl.so +0 -0
  154. a_sync/primitives/locks/prio_semaphore.pxd +25 -0
  155. a_sync/primitives/locks/prio_semaphore.pyi +217 -0
  156. a_sync/primitives/locks/prio_semaphore.pyx +597 -0
  157. a_sync/primitives/locks/semaphore.c +26553 -0
  158. a_sync/primitives/locks/semaphore.cpython-313-i386-linux-musl.so +0 -0
  159. a_sync/primitives/locks/semaphore.pxd +21 -0
  160. a_sync/primitives/locks/semaphore.pyi +197 -0
  161. a_sync/primitives/locks/semaphore.pyx +454 -0
  162. a_sync/primitives/queue.py +1026 -0
  163. a_sync/py.typed +0 -0
  164. a_sync/sphinx/__init__.py +3 -0
  165. a_sync/sphinx/ext.py +289 -0
  166. a_sync/task.py +934 -0
  167. a_sync/utils/__init__.py +105 -0
  168. a_sync/utils/iterators.py +297 -0
  169. a_sync/utils/repr.c +15866 -0
  170. a_sync/utils/repr.cpython-313-i386-linux-musl.so +0 -0
  171. a_sync/utils/repr.pyi +2 -0
  172. a_sync/utils/repr.pyx +73 -0
  173. ez_a_sync-0.33.4.dist-info/METADATA +368 -0
  174. ez_a_sync-0.33.4.dist-info/RECORD +177 -0
  175. ez_a_sync-0.33.4.dist-info/WHEEL +5 -0
  176. ez_a_sync-0.33.4.dist-info/licenses/LICENSE.txt +17 -0
  177. ez_a_sync-0.33.4.dist-info/top_level.txt +1 -0
a_sync/future.py ADDED
@@ -0,0 +1,1497 @@
1
+ # type: ignore [var-annotated]
2
+
3
+ """
4
+ The `future.py` module provides functionality for handling asynchronous futures,
5
+ including a decorator for converting callables into `ASyncFuture` objects and
6
+ utilities for managing asynchronous computations.
7
+
8
+ Functions:
9
+ future(callable: Union[Callable[P, Awaitable[T]], Callable[P, T]] = None, **kwargs: Unpack[ModifierKwargs]) -> Callable[P, Union[T, "ASyncFuture[T]"]]:
10
+ A decorator to convert a callable into an `ASyncFuture`, with optional modifiers.
11
+ _gather_check_and_materialize(*things: Unpack[MaybeAwaitable[T]]) -> List[T]:
12
+ Gathers and materializes a list of awaitable or non-awaitable items.
13
+ _check_and_materialize(thing: T) -> T:
14
+ Checks if an item is awaitable and materializes it.
15
+ _materialize(meta: "ASyncFuture[T]") -> T:
16
+ Materializes the result of an `ASyncFuture`.
17
+
18
+ Classes:
19
+ ASyncFuture: Represents an asynchronous future result.
20
+
21
+ TODO include a simple mathematics example a one complex example with numerous variables and operations
22
+ TODO include attribute access examples
23
+ TODO describe a bit more about both of the above 2 TODOs somewhere in this module-level docstring
24
+ TODO describe why a user would want to use these (to write cleaner code that doesn't require as many ugly gathers)
25
+ TODO include comparisons between the 'new way' with this future class and the 'old way' with gathers
26
+ """
27
+
28
+ import concurrent.futures
29
+ from asyncio import Future, Task, get_event_loop
30
+ from decimal import Decimal
31
+ from functools import partial, wraps
32
+ from inspect import isawaitable
33
+ from typing import (
34
+ TYPE_CHECKING,
35
+ Any,
36
+ Awaitable,
37
+ Callable,
38
+ Dict,
39
+ Generator,
40
+ Generic,
41
+ List,
42
+ Optional,
43
+ Set,
44
+ Type,
45
+ Union,
46
+ final,
47
+ overload,
48
+ )
49
+
50
+ from typing_extensions import Self, Unpack
51
+
52
+ from a_sync._typing import I, P, T, AnyFn, MaybeAwaitable, ModifierKwargs, Numeric
53
+ from a_sync.asyncio import create_task, igather
54
+
55
+ if not TYPE_CHECKING:
56
+ # To prevent circ import issues, we populate this later
57
+ a_sync = None
58
+
59
+ else:
60
+ # this is just here to keep `a_sync` function-colored in the IDE
61
+ from a_sync import a_sync
62
+
63
+
64
+ def future(
65
+ callable: AnyFn[P, T] = None,
66
+ **kwargs: Unpack[ModifierKwargs],
67
+ ) -> Callable[P, Union[T, "ASyncFuture[T]"]]:
68
+ """
69
+ A decorator function to convert a callable into an `ASyncFuture`, with optional modifiers.
70
+
71
+ This function wraps the provided callable in an `_ASyncFutureWrappedFn` instance,
72
+ which returns an `ASyncFuture` when called. The `ASyncFuture` allows the result
73
+ of the callable to be awaited or accessed synchronously.
74
+
75
+ Args:
76
+ callable: The callable to convert. Defaults to None.
77
+ **kwargs: Additional keyword arguments for the modifier.
78
+
79
+ Returns:
80
+ A callable that returns either the result or an `ASyncFuture`.
81
+
82
+ Example:
83
+ >>> @future
84
+ ... async def async_function():
85
+ ... return 42
86
+ >>> result = async_function()
87
+ >>> isinstance(result, ASyncFuture)
88
+ True
89
+
90
+ See Also:
91
+ :class:`ASyncFuture`
92
+ """
93
+ return _ASyncFutureWrappedFn(callable, **kwargs)
94
+
95
+
96
+ async def _gather_check_and_materialize(*things: Unpack[MaybeAwaitable[T]]) -> List[T]:
97
+ """
98
+ Gathers and materializes a list of awaitable or non-awaitable items.
99
+
100
+ This function takes a list of items that may be awaitable or not, and
101
+ returns a list of their results. Awaitable items are awaited, while
102
+ non-awaitable items are returned as-is.
103
+
104
+ Args:
105
+ *things: Items to gather and materialize.
106
+
107
+ Example:
108
+ >>> async def async_fn(x):
109
+ ... return x
110
+ >>> await _gather_check_and_materialize(async_fn(1), 2, async_fn(3))
111
+ [1, 2, 3]
112
+ """
113
+ return await igather(map(_check_and_materialize, things))
114
+
115
+
116
+ async def _check_and_materialize(thing: T) -> T:
117
+ """
118
+ Checks if an item is awaitable and materializes it.
119
+
120
+ If the item is awaitable, it is awaited and the result is returned.
121
+ Otherwise, the item is returned as-is.
122
+
123
+ Args:
124
+ thing: The item to check and materialize.
125
+
126
+ Example:
127
+ >>> async def async_fn():
128
+ ... return 42
129
+ >>> await _check_and_materialize(async_fn())
130
+ 42
131
+ """
132
+ return await thing if isawaitable(thing) else thing
133
+
134
+
135
+ def _materialize(meta: "ASyncFuture[T]") -> T:
136
+ """
137
+ Materializes the result of an `ASyncFuture`.
138
+
139
+ This function attempts to run the event loop until the `ASyncFuture` is complete.
140
+ If the event loop is already running, it raises a RuntimeError.
141
+
142
+ Args:
143
+ meta: The `ASyncFuture` to materialize.
144
+
145
+ Raises:
146
+ RuntimeError: If the event loop is running and the result cannot be awaited.
147
+
148
+ Example:
149
+ >>> future = ASyncFuture(asyncio.sleep(1, result=42))
150
+ >>> _materialize(future)
151
+ 42
152
+
153
+ See Also:
154
+ :class:`ASyncFuture`
155
+ """
156
+ try:
157
+ return get_event_loop().run_until_complete(meta)
158
+ except RuntimeError as e:
159
+ raise RuntimeError(
160
+ f"{meta} result is not set and the event loop is running, you will need to await it first"
161
+ ) from e
162
+
163
+
164
+ MetaNumeric = Union[Numeric, "ASyncFuture[int]", "ASyncFuture[float]", "ASyncFuture[Decimal]"]
165
+
166
+ _cf_init = concurrent.futures.Future.__init__
167
+ _cf_result = concurrent.futures.Future.result
168
+
169
+
170
+ @final
171
+ class ASyncFuture(concurrent.futures.Future, Awaitable[T]):
172
+ """
173
+ A class representing an asynchronous future result.
174
+
175
+ Inherits from both `concurrent.futures.Future` and `Awaitable[T]`, allowing it to be used in both synchronous and asynchronous contexts.
176
+
177
+ The `ASyncFuture` class provides additional functionality for arithmetic operations,
178
+ comparisons, and conversions, making it versatile for various use cases.
179
+
180
+ Example:
181
+ >>> async def async_fn():
182
+ ... return 42
183
+ >>> future = ASyncFuture(async_fn())
184
+ >>> await future
185
+ 42
186
+
187
+ Note:
188
+ Arithmetic operations are implemented, allowing for mathematical operations on future results.
189
+ You no longer have to choose between optimized async code and clean, readable code.
190
+
191
+ Example:
192
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
193
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=5))
194
+ >>> future3 = ASyncFuture(asyncio.sleep(1, result=10))
195
+ >>> future4 = ASyncFuture(asyncio.sleep(1, result=2))
196
+ >>> result = (future1 + future2) / future3 ** future4
197
+ >>> await result
198
+ 0.15
199
+
200
+ Attribute Access:
201
+ The `ASyncFuture` allows attribute access on the materialized result.
202
+
203
+ Example:
204
+ >>> class Example:
205
+ ... def __init__(self, value):
206
+ ... self.value = value
207
+ >>> future = ASyncFuture(asyncio.sleep(1, result=Example(42)))
208
+ >>> future.value
209
+ 42
210
+
211
+ See Also:
212
+ :func:`future` for creating `ASyncFuture` instances.
213
+ """
214
+
215
+ __slots__ = "__awaitable__", "__dependencies", "__dependants", "__task"
216
+
217
+ def __init__(
218
+ self, awaitable: Awaitable[T], dependencies: List["ASyncFuture"] = []
219
+ ) -> None: # sourcery skip: default-mutable-arg
220
+ """
221
+ Initializes an `ASyncFuture` with an awaitable and optional dependencies.
222
+
223
+ Args:
224
+ awaitable: The awaitable object.
225
+ dependencies: A list of dependencies. Defaults to [].
226
+
227
+ Example:
228
+ >>> async def async_fn():
229
+ ... return 42
230
+ >>> future = ASyncFuture(async_fn())
231
+ >>> await future
232
+ 42
233
+ """
234
+
235
+ self.__awaitable__ = awaitable
236
+ """The awaitable object."""
237
+
238
+ self.__dependencies = dependencies
239
+ """A list of dependencies."""
240
+
241
+ for dependency in dependencies:
242
+ assert isinstance(dependency, ASyncFuture)
243
+ dependency.__dependants.append(self)
244
+
245
+ self.__dependants: List[ASyncFuture] = []
246
+ """A list of dependants."""
247
+
248
+ self.__task = None
249
+ """The task associated with the awaitable."""
250
+
251
+ _cf_init(self)
252
+
253
+ def __hash__(self) -> int:
254
+ return hash(self.__awaitable__)
255
+
256
+ def __repr__(self) -> str:
257
+ string = f"<{self.__class__.__name__} {self._state} for {self.__awaitable__}"
258
+ if self.cancelled():
259
+ pass
260
+ elif self.done():
261
+ string += (
262
+ f" exception={self.exception()}"
263
+ if self.exception()
264
+ else f" result={_cf_result(self)}"
265
+ )
266
+ return f"{string}>"
267
+
268
+ def __list_dependencies(self, other) -> List["ASyncFuture"]:
269
+ """
270
+ Lists dependencies for the `ASyncFuture`.
271
+
272
+ Args:
273
+ other: The other dependency to list.
274
+
275
+ Returns:
276
+ A list of dependencies including the current and other `ASyncFuture`.
277
+ """
278
+ return [self, other] if isinstance(other, ASyncFuture) else [self]
279
+
280
+ @property
281
+ def result(self) -> Union[Callable[[], T], Any]:
282
+ # sourcery skip: assign-if-exp, reintroduce-else
283
+ """
284
+ If this future is not done, it will work like `cf.Future.result`. It will block, await the awaitable, and return the result when ready.
285
+ If this future is done and the result has attribute `result`, will return `getattr(future_result, 'result')`
286
+ If this future is done and the result does NOT have attribute `result`, will again work like `cf.Future.result`
287
+
288
+ Example:
289
+ >>> future = ASyncFuture(asyncio.sleep(1, result=42))
290
+ >>> future.result()
291
+ 42
292
+ """
293
+ if self.done():
294
+ if hasattr(r := _cf_result(self), "result"):
295
+ # can be property, method, whatever. should work.
296
+ return r.result
297
+ # the result should be callable like an asyncio.Future
298
+ return lambda: _cf_result(self)
299
+ return lambda: _materialize(self)
300
+
301
+ def __getattr__(self, attr: str) -> Any:
302
+ """
303
+ Allows access to attributes of the materialized result.
304
+
305
+ Args:
306
+ attr: The attribute name to access.
307
+
308
+ Returns:
309
+ The attribute value from the materialized result.
310
+
311
+ Example:
312
+ >>> class Example:
313
+ ... def __init__(self, value):
314
+ ... self.value = value
315
+ >>> future = ASyncFuture(asyncio.sleep(1, result=Example(42)))
316
+ >>> future.value
317
+ 42
318
+ """
319
+ return getattr(_materialize(self), attr)
320
+
321
+ def __getitem__(self, key) -> Any:
322
+ """
323
+ Allows item access on the materialized result.
324
+
325
+ Args:
326
+ key: The key to access.
327
+
328
+ Returns:
329
+ The item from the materialized result.
330
+
331
+ Example:
332
+ >>> future = ASyncFuture(asyncio.sleep(1, result={'key': 'value'}))
333
+ >>> future['key']
334
+ 'value'
335
+ """
336
+ return _materialize(self)[key]
337
+
338
+ # NOTE: broken, do not use. I think
339
+ def __setitem__(self, key, value) -> None:
340
+ """
341
+ Allows setting an item on the materialized result.
342
+
343
+ Args:
344
+ key: The key to set.
345
+ value: The value to set.
346
+
347
+ Example:
348
+ >>> future = ASyncFuture(asyncio.sleep(1, result={'key': 'value'}))
349
+ >>> future['key'] = 'new_value'
350
+ """
351
+ _materialize(self)[key] = value
352
+
353
+ # not sure what to call these
354
+ def __contains__(self, key: Any) -> bool:
355
+ """
356
+ Checks if a key is in the materialized result.
357
+
358
+ Args:
359
+ key: The key to check.
360
+
361
+ Returns:
362
+ True if the key is in the materialized result, False otherwise.
363
+
364
+ Example:
365
+ >>> future = ASyncFuture(asyncio.sleep(1, result={'key': 'value'}))
366
+ >>> 'key' in future
367
+ True
368
+ """
369
+ return _materialize(
370
+ ASyncFuture(self.__contains(key), dependencies=self.__list_dependencies(key))
371
+ )
372
+
373
+ def __await__(self) -> Generator[Any, None, T]:
374
+ """
375
+ Makes the `ASyncFuture` awaitable.
376
+
377
+ Example:
378
+ >>> future = ASyncFuture(asyncio.sleep(1, result=42))
379
+ >>> await future
380
+ 42
381
+ """
382
+ return self.__await().__await__()
383
+
384
+ async def __await(self) -> T:
385
+ if not self.done():
386
+ self.set_result(await self.__task__)
387
+ return self._result
388
+
389
+ @property
390
+ def __task__(self) -> "Task[T]":
391
+ """
392
+ Returns the asyncio task associated with the awaitable, creating it if necessary.
393
+
394
+ Example:
395
+ >>> future = ASyncFuture(asyncio.sleep(1, result=42))
396
+ >>> task = future.__task__
397
+ >>> isinstance(task, asyncio.Task)
398
+ True
399
+ """
400
+ if self.__task is None:
401
+ self.__task = create_task(self.__awaitable__)
402
+ return self.__task
403
+
404
+ def __iter__(self):
405
+ """
406
+ Returns an iterator for the materialized result.
407
+
408
+ Example:
409
+ >>> future = ASyncFuture(asyncio.sleep(1, result=[1, 2, 3]))
410
+ >>> for item in future:
411
+ ... print(item)
412
+ 1
413
+ 2
414
+ 3
415
+ """
416
+ return _materialize(self).__iter__()
417
+
418
+ def __next__(self):
419
+ """
420
+ Returns the next item from the materialized result.
421
+
422
+ Example:
423
+ >>> future = ASyncFuture(asyncio.sleep(1, result=iter([1, 2, 3])))
424
+ >>> next(future)
425
+ 1
426
+ """
427
+ return _materialize(self).__next__()
428
+
429
+ def __enter__(self):
430
+ """
431
+ Enters the context of the materialized result.
432
+
433
+ Example:
434
+ >>> class SomeContext:
435
+ ... def __enter__(self):
436
+ ... return self
437
+ ... def __exit__(self, exc_type, exc_val, exc_tb):
438
+ ... pass
439
+ >>> future = ASyncFuture(asyncio.sleep(1, result=SomeContext()))
440
+ >>> with future as context:
441
+ ... context.do_something()
442
+ """
443
+ return _materialize(self).__enter__()
444
+
445
+ def __exit__(self, *args):
446
+ """
447
+ Exits the context of the materialized result.
448
+
449
+ Example:
450
+ >>> class SomeContext:
451
+ ... def __enter__(self):
452
+ ... return self
453
+ ... def __exit__(self, exc_type, exc_val, exc_tb):
454
+ ... pass
455
+ >>> future = ASyncFuture(asyncio.sleep(1, result=SomeContext()))
456
+ >>> with future as context:
457
+ ... pass
458
+ >>> # Context is exited here
459
+ """
460
+ return _materialize(self).__exit__(*args)
461
+
462
+ @overload
463
+ def __add__(self: "ASyncFuture[int]", other: int) -> "ASyncFuture[int]": ...
464
+
465
+ @overload
466
+ def __add__(self: "ASyncFuture[float]", other: float) -> "ASyncFuture[float]": ...
467
+
468
+ @overload
469
+ def __add__(self: "ASyncFuture[float]", other: int) -> "ASyncFuture[float]": ...
470
+
471
+ @overload
472
+ def __add__(self: "ASyncFuture[int]", other: float) -> "ASyncFuture[float]": ...
473
+
474
+ @overload
475
+ def __add__(self: "ASyncFuture[Decimal]", other: Decimal) -> "ASyncFuture[Decimal]": ...
476
+
477
+ @overload
478
+ def __add__(self: "ASyncFuture[Decimal]", other: int) -> "ASyncFuture[Decimal]": ...
479
+
480
+ @overload
481
+ def __add__(self: "ASyncFuture[int]", other: Decimal) -> "ASyncFuture[Decimal]": ...
482
+
483
+ @overload
484
+ def __add__(self: "ASyncFuture[int]", other: Awaitable[int]) -> "ASyncFuture[int]": ...
485
+
486
+ @overload
487
+ def __add__(self: "ASyncFuture[float]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
488
+
489
+ @overload
490
+ def __add__(self: "ASyncFuture[float]", other: Awaitable[int]) -> "ASyncFuture[float]": ...
491
+
492
+ @overload
493
+ def __add__(self: "ASyncFuture[int]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
494
+
495
+ @overload
496
+ def __add__(
497
+ self: "ASyncFuture[Decimal]", other: Awaitable[Decimal]
498
+ ) -> "ASyncFuture[Decimal]": ...
499
+
500
+ @overload
501
+ def __add__(self: "ASyncFuture[Decimal]", other: Awaitable[int]) -> "ASyncFuture[Decimal]": ...
502
+
503
+ @overload
504
+ def __add__(self: "ASyncFuture[int]", other: Awaitable[Decimal]) -> "ASyncFuture[Decimal]": ...
505
+
506
+ def __add__(self, other: MetaNumeric) -> "ASyncFuture":
507
+ """
508
+ Adds the result of this `ASyncFuture` to another value or `ASyncFuture`.
509
+
510
+ Args:
511
+ other: The value or `ASyncFuture` to add.
512
+
513
+ Returns:
514
+ A new `ASyncFuture` representing the sum.
515
+
516
+ Example:
517
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
518
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=5))
519
+ >>> result = future1 + future2
520
+ >>> await result
521
+ 15
522
+ """
523
+ return ASyncFuture(self.__add(other), dependencies=self.__list_dependencies(other))
524
+
525
+ @overload
526
+ def __sub__(self: "ASyncFuture[int]", other: int) -> "ASyncFuture[int]": ...
527
+
528
+ @overload
529
+ def __sub__(self: "ASyncFuture[float]", other: float) -> "ASyncFuture[float]": ...
530
+
531
+ @overload
532
+ def __sub__(self: "ASyncFuture[float]", other: int) -> "ASyncFuture[float]": ...
533
+
534
+ @overload
535
+ def __sub__(self: "ASyncFuture[int]", other: float) -> "ASyncFuture[float]": ...
536
+
537
+ @overload
538
+ def __sub__(self: "ASyncFuture[Decimal]", other: Decimal) -> "ASyncFuture[Decimal]": ...
539
+
540
+ @overload
541
+ def __sub__(self: "ASyncFuture[Decimal]", other: int) -> "ASyncFuture[Decimal]": ...
542
+
543
+ @overload
544
+ def __sub__(self: "ASyncFuture[int]", other: Decimal) -> "ASyncFuture[Decimal]": ...
545
+
546
+ @overload
547
+ def __sub__(self: "ASyncFuture[int]", other: Awaitable[int]) -> "ASyncFuture[int]": ...
548
+
549
+ @overload
550
+ def __sub__(self: "ASyncFuture[float]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
551
+
552
+ @overload
553
+ def __sub__(self: "ASyncFuture[float]", other: Awaitable[int]) -> "ASyncFuture[float]": ...
554
+
555
+ @overload
556
+ def __sub__(self: "ASyncFuture[int]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
557
+
558
+ @overload
559
+ def __sub__(
560
+ self: "ASyncFuture[Decimal]", other: Awaitable[Decimal]
561
+ ) -> "ASyncFuture[Decimal]": ...
562
+
563
+ @overload
564
+ def __sub__(self: "ASyncFuture[Decimal]", other: Awaitable[int]) -> "ASyncFuture[Decimal]": ...
565
+
566
+ @overload
567
+ def __sub__(self: "ASyncFuture[int]", other: Awaitable[Decimal]) -> "ASyncFuture[Decimal]": ...
568
+
569
+ def __sub__(self, other: MetaNumeric) -> "ASyncFuture":
570
+ """
571
+ Subtracts another value or `ASyncFuture` from the result of this `ASyncFuture`.
572
+
573
+ Args:
574
+ other: The value or `ASyncFuture` to subtract.
575
+
576
+ Returns:
577
+ A new `ASyncFuture` representing the difference.
578
+
579
+ Example:
580
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
581
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=5))
582
+ >>> result = future1 - future2
583
+ >>> await result
584
+ 5
585
+ """
586
+ return ASyncFuture(self.__sub(other), dependencies=self.__list_dependencies(other))
587
+
588
+ def __mul__(self, other) -> "ASyncFuture":
589
+ """
590
+ Multiplies the result of this `ASyncFuture` by another value or `ASyncFuture`.
591
+
592
+ Args:
593
+ other: The value or `ASyncFuture` to multiply.
594
+
595
+ Returns:
596
+ A new `ASyncFuture` representing the product.
597
+
598
+ Example:
599
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
600
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=5))
601
+ >>> result = future1 * future2
602
+ >>> await result
603
+ 50
604
+ """
605
+ return ASyncFuture(self.__mul(other), dependencies=self.__list_dependencies(other))
606
+
607
+ def __pow__(self, other) -> "ASyncFuture":
608
+ """
609
+ Raises the result of this `ASyncFuture` to the power of another value or `ASyncFuture`.
610
+
611
+ Args:
612
+ other: The exponent value or `ASyncFuture`.
613
+
614
+ Returns:
615
+ A new `ASyncFuture` representing the power.
616
+
617
+ Example:
618
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=2))
619
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=3))
620
+ >>> result = future1 ** future2
621
+ >>> await result
622
+ 8
623
+ """
624
+ return ASyncFuture(self.__pow(other), dependencies=self.__list_dependencies(other))
625
+
626
+ def __truediv__(self, other) -> "ASyncFuture":
627
+ """
628
+ Divides the result of this `ASyncFuture` by another value or `ASyncFuture`.
629
+
630
+ Args:
631
+ other: The divisor value or `ASyncFuture`.
632
+
633
+ Returns:
634
+ A new `ASyncFuture` representing the quotient.
635
+
636
+ Example:
637
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
638
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=2))
639
+ >>> result = future1 / future2
640
+ >>> await result
641
+ 5.0
642
+ """
643
+ return ASyncFuture(self.__truediv(other), dependencies=self.__list_dependencies(other))
644
+
645
+ def __floordiv__(self, other) -> "ASyncFuture":
646
+ """
647
+ Performs floor division of the result of this `ASyncFuture` by another value or `ASyncFuture`.
648
+
649
+ Args:
650
+ other: The divisor value or `ASyncFuture`.
651
+
652
+ Returns:
653
+ A new `ASyncFuture` representing the floor division result.
654
+
655
+ Example:
656
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
657
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=3))
658
+ >>> result = future1 // future2
659
+ >>> await result
660
+ 3
661
+ """
662
+ return ASyncFuture(self.__floordiv(other), dependencies=self.__list_dependencies(other))
663
+
664
+ def __pow__(self, other) -> "ASyncFuture":
665
+ """
666
+ Raises the result of this `ASyncFuture` to the power of another value or `ASyncFuture`.
667
+
668
+ Args:
669
+ other: The exponent value or `ASyncFuture`.
670
+
671
+ Returns:
672
+ A new `ASyncFuture` representing the power.
673
+
674
+ Example:
675
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=2))
676
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=3))
677
+ >>> result = future1 ** future2
678
+ >>> await result
679
+ 8
680
+ """
681
+ return ASyncFuture(self.__pow(other), dependencies=self.__list_dependencies(other))
682
+
683
+ @overload
684
+ def __radd__(self: "ASyncFuture[int]", other: int) -> "ASyncFuture[int]": ...
685
+
686
+ @overload
687
+ def __radd__(self: "ASyncFuture[float]", other: float) -> "ASyncFuture[float]": ...
688
+
689
+ @overload
690
+ def __radd__(self: "ASyncFuture[float]", other: int) -> "ASyncFuture[float]": ...
691
+
692
+ @overload
693
+ def __radd__(self: "ASyncFuture[int]", other: float) -> "ASyncFuture[float]": ...
694
+
695
+ @overload
696
+ def __radd__(self: "ASyncFuture[Decimal]", other: Decimal) -> "ASyncFuture[Decimal]": ...
697
+
698
+ @overload
699
+ def __radd__(self: "ASyncFuture[Decimal]", other: int) -> "ASyncFuture[Decimal]": ...
700
+
701
+ @overload
702
+ def __radd__(self: "ASyncFuture[int]", other: Decimal) -> "ASyncFuture[Decimal]": ...
703
+
704
+ @overload
705
+ def __radd__(self: "ASyncFuture[int]", other: Awaitable[int]) -> "ASyncFuture[int]": ...
706
+
707
+ @overload
708
+ def __radd__(self: "ASyncFuture[float]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
709
+
710
+ @overload
711
+ def __radd__(self: "ASyncFuture[float]", other: Awaitable[int]) -> "ASyncFuture[float]": ...
712
+
713
+ @overload
714
+ def __radd__(self: "ASyncFuture[int]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
715
+
716
+ @overload
717
+ def __radd__(
718
+ self: "ASyncFuture[Decimal]", other: Awaitable[Decimal]
719
+ ) -> "ASyncFuture[Decimal]": ...
720
+
721
+ @overload
722
+ def __radd__(self: "ASyncFuture[Decimal]", other: Awaitable[int]) -> "ASyncFuture[Decimal]": ...
723
+
724
+ @overload
725
+ def __radd__(self: "ASyncFuture[int]", other: Awaitable[Decimal]) -> "ASyncFuture[Decimal]": ...
726
+
727
+ def __radd__(self, other) -> "ASyncFuture":
728
+ """
729
+ Adds another value or `ASyncFuture` to the result of this `ASyncFuture`.
730
+
731
+ Args:
732
+ other: The value or `ASyncFuture` to add.
733
+
734
+ Returns:
735
+ A new `ASyncFuture` representing the sum.
736
+
737
+ Example:
738
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
739
+ >>> result = 5 + future1
740
+ >>> await result
741
+ 15
742
+ """
743
+ return ASyncFuture(self.__radd(other), dependencies=self.__list_dependencies(other))
744
+
745
+ @overload
746
+ def __rsub__(self: "ASyncFuture[int]", other: int) -> "ASyncFuture[int]": ...
747
+
748
+ @overload
749
+ def __rsub__(self: "ASyncFuture[float]", other: float) -> "ASyncFuture[float]": ...
750
+
751
+ @overload
752
+ def __rsub__(self: "ASyncFuture[float]", other: int) -> "ASyncFuture[float]": ...
753
+
754
+ @overload
755
+ def __rsub__(self: "ASyncFuture[int]", other: float) -> "ASyncFuture[float]": ...
756
+
757
+ @overload
758
+ def __rsub__(self: "ASyncFuture[Decimal]", other: Decimal) -> "ASyncFuture[Decimal]": ...
759
+
760
+ @overload
761
+ def __rsub__(self: "ASyncFuture[Decimal]", other: int) -> "ASyncFuture[Decimal]": ...
762
+
763
+ @overload
764
+ def __rsub__(self: "ASyncFuture[int]", other: Decimal) -> "ASyncFuture[Decimal]": ...
765
+
766
+ @overload
767
+ def __rsub__(self: "ASyncFuture[int]", other: Awaitable[int]) -> "ASyncFuture[int]": ...
768
+
769
+ @overload
770
+ def __rsub__(self: "ASyncFuture[float]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
771
+
772
+ @overload
773
+ def __rsub__(self: "ASyncFuture[float]", other: Awaitable[int]) -> "ASyncFuture[float]": ...
774
+
775
+ @overload
776
+ def __rsub__(self: "ASyncFuture[int]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
777
+
778
+ @overload
779
+ def __rsub__(
780
+ self: "ASyncFuture[Decimal]", other: Awaitable[Decimal]
781
+ ) -> "ASyncFuture[Decimal]": ...
782
+
783
+ @overload
784
+ def __rsub__(self: "ASyncFuture[Decimal]", other: Awaitable[int]) -> "ASyncFuture[Decimal]": ...
785
+
786
+ @overload
787
+ def __rsub__(self: "ASyncFuture[int]", other: Awaitable[Decimal]) -> "ASyncFuture[Decimal]": ...
788
+
789
+ def __rsub__(self, other) -> "ASyncFuture":
790
+ """
791
+ Subtracts the result of this `ASyncFuture` from another value or `ASyncFuture`.
792
+
793
+ Args:
794
+ other: The value or `ASyncFuture` to subtract from.
795
+
796
+ Returns:
797
+ A new `ASyncFuture` representing the difference.
798
+
799
+ Example:
800
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
801
+ >>> result = 20 - future1
802
+ >>> await result
803
+ 10
804
+ """
805
+ return ASyncFuture(self.__rsub(other), dependencies=self.__list_dependencies(other))
806
+
807
+ def __rmul__(self, other) -> "ASyncFuture":
808
+ """
809
+ Multiplies another value or `ASyncFuture` by the result of this `ASyncFuture`.
810
+
811
+ Args:
812
+ other: The value or `ASyncFuture` to multiply.
813
+
814
+ Returns:
815
+ A new `ASyncFuture` representing the product.
816
+
817
+ Example:
818
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
819
+ >>> result = 2 * future1
820
+ >>> await result
821
+ 20
822
+ """
823
+ return ASyncFuture(self.__rmul(other), dependencies=self.__list_dependencies(other))
824
+
825
+ def __rtruediv__(self, other) -> "ASyncFuture":
826
+ """
827
+ Divides another value or `ASyncFuture` by the result of this `ASyncFuture`.
828
+
829
+ Args:
830
+ other: The value or `ASyncFuture` to divide.
831
+
832
+ Returns:
833
+ A new `ASyncFuture` representing the quotient.
834
+
835
+ Example:
836
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=2))
837
+ >>> result = 10 / future1
838
+ >>> await result
839
+ 5.0
840
+ """
841
+ return ASyncFuture(self.__rtruediv(other), dependencies=self.__list_dependencies(other))
842
+
843
+ def __rfloordiv__(self, other) -> "ASyncFuture":
844
+ """
845
+ Performs floor division of another value or `ASyncFuture` by the result of this `ASyncFuture`.
846
+
847
+ Args:
848
+ other: The value or `ASyncFuture` to divide.
849
+
850
+ Returns:
851
+ A new `ASyncFuture` representing the floor division result.
852
+
853
+ Example:
854
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=3))
855
+ >>> result = 10 // future1
856
+ >>> await result
857
+ 3
858
+ """
859
+ return ASyncFuture(self.__rfloordiv(other), dependencies=self.__list_dependencies(other))
860
+
861
+ def __rpow__(self, other) -> "ASyncFuture":
862
+ """
863
+ Raises another value or `ASyncFuture` to the power of the result of this `ASyncFuture`.
864
+
865
+ Args:
866
+ other: The base value or `ASyncFuture`.
867
+
868
+ Returns:
869
+ A new `ASyncFuture` representing the power.
870
+
871
+ Example:
872
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=3))
873
+ >>> result = 2 ** future1
874
+ >>> await result
875
+ 8
876
+ """
877
+ return ASyncFuture(self.__rpow(other), dependencies=self.__list_dependencies(other))
878
+
879
+ def __eq__(self, other) -> "ASyncFuture":
880
+ """
881
+ Compares the result of this `ASyncFuture` with another value or `ASyncFuture` for equality.
882
+
883
+ Args:
884
+ other: The value or `ASyncFuture` to compare.
885
+
886
+ Returns:
887
+ A new `ASyncFuture` representing the equality comparison result.
888
+
889
+ Example:
890
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
891
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=10))
892
+ >>> result = future1 == future2
893
+ >>> await result
894
+ True
895
+ """
896
+ return bool(ASyncFuture(self.__eq(other), dependencies=self.__list_dependencies(other)))
897
+
898
+ def __gt__(self, other) -> "ASyncFuture":
899
+ """
900
+ Compares the result of this `ASyncFuture` with another value or `ASyncFuture` for greater than.
901
+
902
+ Args:
903
+ other: The value or `ASyncFuture` to compare.
904
+
905
+ Returns:
906
+ A new `ASyncFuture` representing the greater than comparison result.
907
+
908
+ Example:
909
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
910
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=5))
911
+ >>> result = future1 > future2
912
+ >>> await result
913
+ True
914
+ """
915
+ return ASyncFuture(self.__gt(other), dependencies=self.__list_dependencies(other))
916
+
917
+ def __ge__(self, other) -> "ASyncFuture":
918
+ """
919
+ Compares the result of this `ASyncFuture` with another value or `ASyncFuture` for greater than or equal.
920
+
921
+ Args:
922
+ other: The value or `ASyncFuture` to compare.
923
+
924
+ Returns:
925
+ A new `ASyncFuture` representing the greater than or equal comparison result.
926
+
927
+ Example:
928
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=10))
929
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=10))
930
+ >>> result = future1 >= future2
931
+ >>> await result
932
+ True
933
+ """
934
+ return ASyncFuture(self.__ge(other), dependencies=self.__list_dependencies(other))
935
+
936
+ def __lt__(self, other) -> "ASyncFuture":
937
+ """
938
+ Compares the result of this `ASyncFuture` with another value or `ASyncFuture` for less than.
939
+
940
+ Args:
941
+ other: The value or `ASyncFuture` to compare.
942
+
943
+ Returns:
944
+ A new `ASyncFuture` representing the less than comparison result.
945
+
946
+ Example:
947
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=5))
948
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=10))
949
+ >>> result = future1 < future2
950
+ >>> await result
951
+ True
952
+ """
953
+ return ASyncFuture(self.__lt(other), dependencies=self.__list_dependencies(other))
954
+
955
+ def __le__(self, other) -> "ASyncFuture":
956
+ """
957
+ Compares the result of this `ASyncFuture` with another value or `ASyncFuture` for less than or equal.
958
+
959
+ Args:
960
+ other: The value or `ASyncFuture` to compare.
961
+
962
+ Returns:
963
+ A new `ASyncFuture` representing the less than or equal comparison result.
964
+
965
+ Example:
966
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=5))
967
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=5))
968
+ >>> result = future1 <= future2
969
+ >>> await result
970
+ True
971
+ """
972
+ return ASyncFuture(self.__le(other), dependencies=self.__list_dependencies(other))
973
+
974
+ # Maths
975
+
976
+ @overload
977
+ async def __add(self: "ASyncFuture[int]", other: int) -> "ASyncFuture[int]": ...
978
+
979
+ @overload
980
+ async def __add(self: "ASyncFuture[float]", other: float) -> "ASyncFuture[float]": ...
981
+
982
+ @overload
983
+ async def __add(self: "ASyncFuture[float]", other: int) -> "ASyncFuture[float]": ...
984
+
985
+ @overload
986
+ async def __add(self: "ASyncFuture[int]", other: float) -> "ASyncFuture[float]": ...
987
+
988
+ @overload
989
+ async def __add(self: "ASyncFuture[Decimal]", other: Decimal) -> "ASyncFuture[Decimal]": ...
990
+
991
+ @overload
992
+ async def __add(self: "ASyncFuture[Decimal]", other: int) -> "ASyncFuture[Decimal]": ...
993
+
994
+ @overload
995
+ async def __add(self: "ASyncFuture[int]", other: Decimal) -> "ASyncFuture[Decimal]": ...
996
+
997
+ @overload
998
+ async def __add(self: "ASyncFuture[int]", other: Awaitable[int]) -> "ASyncFuture[int]": ...
999
+
1000
+ @overload
1001
+ async def __add(
1002
+ self: "ASyncFuture[float]", other: Awaitable[float]
1003
+ ) -> "ASyncFuture[float]": ...
1004
+
1005
+ @overload
1006
+ async def __add(self: "ASyncFuture[float]", other: Awaitable[int]) -> "ASyncFuture[float]": ...
1007
+
1008
+ @overload
1009
+ async def __add(self: "ASyncFuture[int]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
1010
+
1011
+ @overload
1012
+ async def __add(
1013
+ self: "ASyncFuture[Decimal]", other: Awaitable[Decimal]
1014
+ ) -> "ASyncFuture[Decimal]": ...
1015
+
1016
+ @overload
1017
+ async def __add(
1018
+ self: "ASyncFuture[Decimal]", other: Awaitable[int]
1019
+ ) -> "ASyncFuture[Decimal]": ...
1020
+
1021
+ @overload
1022
+ async def __add(
1023
+ self: "ASyncFuture[int]", other: Awaitable[Decimal]
1024
+ ) -> "ASyncFuture[Decimal]": ...
1025
+
1026
+ async def __add(self, other) -> "Any":
1027
+ a, b = await _gather_check_and_materialize(self, other)
1028
+ return a + b
1029
+
1030
+ @overload
1031
+ async def __sub(self: "ASyncFuture[int]", other: int) -> "ASyncFuture[int]": ...
1032
+
1033
+ @overload
1034
+ async def __sub(self: "ASyncFuture[float]", other: float) -> "ASyncFuture[float]": ...
1035
+
1036
+ @overload
1037
+ async def __sub(self: "ASyncFuture[float]", other: int) -> "ASyncFuture[float]": ...
1038
+
1039
+ @overload
1040
+ async def __sub(self: "ASyncFuture[int]", other: float) -> "ASyncFuture[float]": ...
1041
+
1042
+ @overload
1043
+ async def __sub(self: "ASyncFuture[Decimal]", other: Decimal) -> "ASyncFuture[Decimal]": ...
1044
+
1045
+ @overload
1046
+ async def __sub(self: "ASyncFuture[Decimal]", other: int) -> "ASyncFuture[Decimal]": ...
1047
+
1048
+ @overload
1049
+ async def __sub(self: "ASyncFuture[int]", other: Decimal) -> "ASyncFuture[Decimal]": ...
1050
+
1051
+ @overload
1052
+ async def __sub(self: "ASyncFuture[int]", other: Awaitable[int]) -> "ASyncFuture[int]": ...
1053
+
1054
+ @overload
1055
+ async def __sub(
1056
+ self: "ASyncFuture[float]", other: Awaitable[float]
1057
+ ) -> "ASyncFuture[float]": ...
1058
+
1059
+ @overload
1060
+ async def __sub(self: "ASyncFuture[float]", other: Awaitable[int]) -> "ASyncFuture[float]": ...
1061
+
1062
+ @overload
1063
+ async def __sub(self: "ASyncFuture[int]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
1064
+
1065
+ @overload
1066
+ async def __sub(
1067
+ self: "ASyncFuture[Decimal]", other: Awaitable[Decimal]
1068
+ ) -> "ASyncFuture[Decimal]": ...
1069
+
1070
+ @overload
1071
+ async def __sub(
1072
+ self: "ASyncFuture[Decimal]", other: Awaitable[int]
1073
+ ) -> "ASyncFuture[Decimal]": ...
1074
+
1075
+ @overload
1076
+ async def __sub(
1077
+ self: "ASyncFuture[int]", other: Awaitable[Decimal]
1078
+ ) -> "ASyncFuture[Decimal]": ...
1079
+
1080
+ async def __sub(self, other) -> "Any":
1081
+ a, b = await _gather_check_and_materialize(self, other)
1082
+ return a - b
1083
+
1084
+ async def __mul(self, other) -> "Any":
1085
+ a, b = await _gather_check_and_materialize(self, other)
1086
+ return a * b
1087
+
1088
+ async def __truediv(self, other) -> "Any":
1089
+ a, b = await _gather_check_and_materialize(self, other)
1090
+ return a / b
1091
+
1092
+ async def __floordiv(self, other) -> "Any":
1093
+ a, b = await _gather_check_and_materialize(self, other)
1094
+ return a // b
1095
+
1096
+ async def __pow(self, other) -> "Any":
1097
+ a, b = await _gather_check_and_materialize(self, other)
1098
+ return a**b
1099
+
1100
+ # rMaths
1101
+ @overload
1102
+ async def __radd(self: "ASyncFuture[int]", other: int) -> "ASyncFuture[int]": ...
1103
+
1104
+ @overload
1105
+ async def __radd(self: "ASyncFuture[float]", other: float) -> "ASyncFuture[float]": ...
1106
+
1107
+ @overload
1108
+ async def __radd(self: "ASyncFuture[float]", other: int) -> "ASyncFuture[float]": ...
1109
+
1110
+ @overload
1111
+ async def __radd(self: "ASyncFuture[int]", other: float) -> "ASyncFuture[float]": ...
1112
+
1113
+ @overload
1114
+ async def __radd(self: "ASyncFuture[Decimal]", other: Decimal) -> "ASyncFuture[Decimal]": ...
1115
+
1116
+ @overload
1117
+ async def __radd(self: "ASyncFuture[Decimal]", other: int) -> "ASyncFuture[Decimal]": ...
1118
+
1119
+ @overload
1120
+ async def __radd(self: "ASyncFuture[int]", other: Decimal) -> "ASyncFuture[Decimal]": ...
1121
+
1122
+ @overload
1123
+ async def __radd(self: "ASyncFuture[int]", other: Awaitable[int]) -> "ASyncFuture[int]": ...
1124
+
1125
+ @overload
1126
+ async def __radd(
1127
+ self: "ASyncFuture[float]", other: Awaitable[float]
1128
+ ) -> "ASyncFuture[float]": ...
1129
+
1130
+ @overload
1131
+ async def __radd(self: "ASyncFuture[float]", other: Awaitable[int]) -> "ASyncFuture[float]": ...
1132
+
1133
+ @overload
1134
+ async def __radd(self: "ASyncFuture[int]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
1135
+
1136
+ @overload
1137
+ async def __radd(
1138
+ self: "ASyncFuture[Decimal]", other: Awaitable[Decimal]
1139
+ ) -> "ASyncFuture[Decimal]": ...
1140
+
1141
+ @overload
1142
+ async def __radd(
1143
+ self: "ASyncFuture[Decimal]", other: Awaitable[int]
1144
+ ) -> "ASyncFuture[Decimal]": ...
1145
+
1146
+ @overload
1147
+ async def __radd(
1148
+ self: "ASyncFuture[int]", other: Awaitable[Decimal]
1149
+ ) -> "ASyncFuture[Decimal]": ...
1150
+
1151
+ async def __radd(self, other) -> "Any":
1152
+ a, b = await _gather_check_and_materialize(other, self)
1153
+ return a + b
1154
+
1155
+ @overload
1156
+ async def __rsub(self: "ASyncFuture[int]", other: int) -> "ASyncFuture[int]": ...
1157
+
1158
+ @overload
1159
+ async def __rsub(self: "ASyncFuture[float]", other: float) -> "ASyncFuture[float]": ...
1160
+
1161
+ @overload
1162
+ async def __rsub(self: "ASyncFuture[float]", other: int) -> "ASyncFuture[float]": ...
1163
+
1164
+ @overload
1165
+ async def __rsub(self: "ASyncFuture[int]", other: float) -> "ASyncFuture[float]": ...
1166
+
1167
+ @overload
1168
+ async def __rsub(self: "ASyncFuture[Decimal]", other: Decimal) -> "ASyncFuture[Decimal]": ...
1169
+
1170
+ @overload
1171
+ async def __rsub(self: "ASyncFuture[Decimal]", other: int) -> "ASyncFuture[Decimal]": ...
1172
+
1173
+ @overload
1174
+ async def __rsub(self: "ASyncFuture[int]", other: Decimal) -> "ASyncFuture[Decimal]": ...
1175
+
1176
+ @overload
1177
+ async def __rsub(self: "ASyncFuture[int]", other: Awaitable[int]) -> "ASyncFuture[int]": ...
1178
+
1179
+ @overload
1180
+ async def __rsub(
1181
+ self: "ASyncFuture[float]", other: Awaitable[float]
1182
+ ) -> "ASyncFuture[float]": ...
1183
+
1184
+ @overload
1185
+ async def __rsub(self: "ASyncFuture[float]", other: Awaitable[int]) -> "ASyncFuture[float]": ...
1186
+
1187
+ @overload
1188
+ async def __rsub(self: "ASyncFuture[int]", other: Awaitable[float]) -> "ASyncFuture[float]": ...
1189
+
1190
+ @overload
1191
+ async def __rsub(
1192
+ self: "ASyncFuture[Decimal]", other: Awaitable[Decimal]
1193
+ ) -> "ASyncFuture[Decimal]": ...
1194
+
1195
+ @overload
1196
+ async def __rsub(
1197
+ self: "ASyncFuture[Decimal]", other: Awaitable[int]
1198
+ ) -> "ASyncFuture[Decimal]": ...
1199
+
1200
+ @overload
1201
+ async def __rsub(
1202
+ self: "ASyncFuture[int]", other: Awaitable[Decimal]
1203
+ ) -> "ASyncFuture[Decimal]": ...
1204
+
1205
+ async def __rsub(self, other) -> "Any":
1206
+ a, b = await _gather_check_and_materialize(other, self)
1207
+ return a - b
1208
+
1209
+ async def __rmul(self, other) -> "Any":
1210
+ a, b = await _gather_check_and_materialize(other, self)
1211
+ return a * b
1212
+
1213
+ async def __rtruediv(self, other) -> "Any":
1214
+ a, b = await _gather_check_and_materialize(other, self)
1215
+ return a / b
1216
+
1217
+ async def __rfloordiv(self, other) -> "Any":
1218
+ a, b = await _gather_check_and_materialize(other, self)
1219
+ return a // b
1220
+
1221
+ async def __rpow(self, other) -> "Any":
1222
+ a, b = await _gather_check_and_materialize(other, self)
1223
+ return a**b
1224
+
1225
+ async def __iadd(self, other) -> "Any":
1226
+ a, b = await _gather_check_and_materialize(self, other)
1227
+ self._result = a + b
1228
+ return self._result
1229
+
1230
+ async def __isub(self, other) -> "Any":
1231
+ a, b = await _gather_check_and_materialize(self, other)
1232
+ self._result = a - b
1233
+ return self._result
1234
+
1235
+ async def __imul(self, other) -> "Any":
1236
+ a, b = await _gather_check_and_materialize(self, other)
1237
+ self._result = a * b
1238
+ return self._result
1239
+
1240
+ async def __itruediv(self, other) -> "Any":
1241
+ a, b = await _gather_check_and_materialize(self, other)
1242
+ self._result = a / b
1243
+ return self._result
1244
+
1245
+ async def __ifloordiv(self, other) -> "Any":
1246
+ a, b = await _gather_check_and_materialize(self, other)
1247
+ self._result = a // b
1248
+ return self._result
1249
+
1250
+ async def __ipow(self, other) -> "Any":
1251
+ a, b = await _gather_check_and_materialize(self, other)
1252
+ self._result = a**b
1253
+ return self._result
1254
+
1255
+ # Comparisons
1256
+ async def __eq(self, other) -> bool:
1257
+ a, b = await _gather_check_and_materialize(self, other)
1258
+ return a == b
1259
+
1260
+ async def __gt(self, other) -> bool:
1261
+ a, b = await _gather_check_and_materialize(self, other)
1262
+ return a > b
1263
+
1264
+ async def __ge(self, other) -> bool:
1265
+ a, b = await _gather_check_and_materialize(self, other)
1266
+ return a >= b
1267
+
1268
+ async def __lt(self, other) -> bool:
1269
+ a, b = await _gather_check_and_materialize(self, other)
1270
+ return a < b
1271
+
1272
+ async def __le(self, other) -> bool:
1273
+ a, b = await _gather_check_and_materialize(self, other)
1274
+ return a <= b
1275
+
1276
+ # not sure what to call these
1277
+ async def __contains(self, item: Any) -> bool:
1278
+ _self, _item = await _gather_check_and_materialize(self, item)
1279
+ return _item in _self
1280
+
1281
+ # conversion
1282
+ # NOTE: We aren't allowed to return ASyncFutures here :(
1283
+ def __bool__(self) -> bool:
1284
+ return bool(_materialize(self))
1285
+
1286
+ def __bytes__(self) -> bytes:
1287
+ return bytes(_materialize(self))
1288
+
1289
+ def __str__(self) -> str:
1290
+ return str(_materialize(self))
1291
+
1292
+ def __int__(self) -> int:
1293
+ return int(_materialize(self))
1294
+
1295
+ def __float__(self) -> float:
1296
+ return float(_materialize(self))
1297
+
1298
+ # WIP internals
1299
+
1300
+ @property
1301
+ def __dependants__(self) -> Set["ASyncFuture"]:
1302
+ """
1303
+ Returns the set of dependants for this `ASyncFuture`, including nested dependants.
1304
+
1305
+ Example:
1306
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=42))
1307
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=10), dependencies=[future1])
1308
+ >>> dependants = future1.__dependants__
1309
+ >>> future2 in dependants
1310
+ True
1311
+ """
1312
+ dependants = set()
1313
+ for dep in self.__dependants:
1314
+ dependants.add(dep)
1315
+ dependants.union(dep.__dependants__)
1316
+ return dependants
1317
+
1318
+ @property
1319
+ def __dependencies__(self) -> Set["ASyncFuture"]:
1320
+ """
1321
+ Returns the set of dependencies for this `ASyncFuture`, including nested dependencies.
1322
+
1323
+ Example:
1324
+ >>> future1 = ASyncFuture(asyncio.sleep(1, result=42))
1325
+ >>> future2 = ASyncFuture(asyncio.sleep(1, result=10), dependencies=[future1])
1326
+ >>> dependencies = future2.__dependencies__
1327
+ >>> future1 in dependencies
1328
+ True
1329
+ """
1330
+ dependencies = set()
1331
+ for dep in self.__dependencies:
1332
+ dependencies.add(dep)
1333
+ dependencies.union(dep.__dependencies__)
1334
+ return dependencies
1335
+
1336
+ def __sizeof__(self) -> int:
1337
+ if isinstance(self.__awaitable__, Coroutine):
1338
+ return sum(sys.getsizeof(v) for v in self.__awaitable__.cr_frame.f_locals.values())
1339
+ elif isinstance(self.__awaitable__, Future):
1340
+ raise NotImplementedError
1341
+ raise NotImplementedError
1342
+
1343
+
1344
+ @final
1345
+ class _ASyncFutureWrappedFn(Callable[P, ASyncFuture[T]]):
1346
+ """
1347
+ A callable class to wrap functions and return `ASyncFuture` objects.
1348
+
1349
+ This class is used internally by the `future` decorator to wrap a function
1350
+ and return an `ASyncFuture` when the function is called. It allows the
1351
+ function to be executed asynchronously and its result to be awaited.
1352
+
1353
+ Example:
1354
+ >>> def sync_fn():
1355
+ ... return 42
1356
+ >>> wrapped_fn = _ASyncFutureWrappedFn(sync_fn)
1357
+ >>> future = wrapped_fn()
1358
+ >>> isinstance(future, ASyncFuture)
1359
+ True
1360
+
1361
+ Note:
1362
+ This is not part of the public API. Use the `future` decorator instead.
1363
+ """
1364
+
1365
+ __slots__ = "callable", "wrapped", "_callable_name"
1366
+
1367
+ def __init__(
1368
+ self,
1369
+ callable: AnyFn[P, T] = None,
1370
+ **kwargs: Unpack[ModifierKwargs],
1371
+ ):
1372
+ if a_sync is None:
1373
+ _import_a_sync()
1374
+ assert a_sync is not None
1375
+
1376
+ if callable:
1377
+ self.callable = callable
1378
+ """The callable function."""
1379
+
1380
+ self._callable_name = callable.__name__
1381
+ """The name of the callable function."""
1382
+
1383
+ a_sync_callable = a_sync(callable, default="async", **kwargs)
1384
+
1385
+ @wraps(callable)
1386
+ def future_wrap(*args: P.args, **kwargs: P.kwargs) -> "ASyncFuture[T]":
1387
+ return ASyncFuture(a_sync_callable(*args, **kwargs, sync=False))
1388
+
1389
+ self.wrapped = future_wrap
1390
+ """The wrapped function returning ASyncFuture."""
1391
+ else:
1392
+ self.wrapped = partial(_ASyncFutureWrappedFn, **kwargs)
1393
+
1394
+ def __call__(self, *args: P.args, **kwargs: P.kwargs) -> ASyncFuture[T]:
1395
+ return self.wrapped(*args, **kwargs)
1396
+
1397
+ def __repr__(self) -> str:
1398
+ return f"<{self.__class__.__name__} {self.callable}>"
1399
+
1400
+ def __get__(
1401
+ self, instance: I, owner: Type[I]
1402
+ ) -> Union[Self, "_ASyncFutureInstanceMethod[I, P, T]"]:
1403
+ return self if owner is None else _ASyncFutureInstanceMethod(self, instance)
1404
+
1405
+
1406
+ @final
1407
+ class _ASyncFutureInstanceMethod(Generic[I, P, T]):
1408
+ # NOTE: probably could just replace this with functools.partial
1409
+ """
1410
+ A class to handle instance methods wrapped as `ASyncFuture`.
1411
+
1412
+ This class is used internally to manage instance methods that are wrapped
1413
+ by `_ASyncFutureWrappedFn`. It ensures that the method is bound to the
1414
+ instance and returns an `ASyncFuture` when called.
1415
+
1416
+ Example:
1417
+ >>> class MyClass:
1418
+ ... @_ASyncFutureWrappedFn
1419
+ ... def method(self):
1420
+ ... return 42
1421
+ >>> instance = MyClass()
1422
+ >>> future = instance.method()
1423
+ >>> isinstance(future, ASyncFuture)
1424
+ True
1425
+
1426
+ Note:
1427
+ This is not part of the public API. Use the `future` decorator instead.
1428
+ """
1429
+
1430
+ __module__: str
1431
+ """The module name of the wrapper."""
1432
+
1433
+ __name__: str
1434
+ """The name of the wrapper."""
1435
+
1436
+ __qualname__: str
1437
+ """The qualified name of the wrapper."""
1438
+
1439
+ __doc__: Optional[str]
1440
+ """The docstring of the wrapper."""
1441
+
1442
+ __annotations__: Dict[str, Any]
1443
+ """The annotations of the wrapper."""
1444
+
1445
+ __instance: I
1446
+ """The instance to which the method is bound."""
1447
+
1448
+ __wrapper: _ASyncFutureWrappedFn[P, T]
1449
+ """The wrapper function."""
1450
+
1451
+ def __init__(
1452
+ self,
1453
+ wrapper: _ASyncFutureWrappedFn[P, T],
1454
+ instance: I,
1455
+ ) -> None: # sourcery skip: use-contextlib-suppress
1456
+ try:
1457
+ self.__module__ = wrapper.__module__
1458
+ except AttributeError:
1459
+ pass
1460
+ try:
1461
+ self.__name__ = wrapper.__name__
1462
+ except AttributeError:
1463
+ pass
1464
+ try:
1465
+ self.__qualname__ = wrapper.__qualname__
1466
+ except AttributeError:
1467
+ pass
1468
+ try:
1469
+ self.__doc__ = wrapper.__doc__
1470
+ except AttributeError:
1471
+ pass
1472
+ try:
1473
+ self.__annotations__ = wrapper.__annotations__
1474
+ except AttributeError:
1475
+ pass
1476
+ try:
1477
+ self.__dict__.update(wrapper.__dict__)
1478
+ except AttributeError:
1479
+ pass
1480
+ self.__instance = instance
1481
+ self.__wrapper = wrapper
1482
+
1483
+ def __repr__(self) -> str:
1484
+ return (
1485
+ f"<{self.__class__.__name__} for {self.__wrapper.callable} bound to {self.__instance}>"
1486
+ )
1487
+
1488
+ def __call__(self, /, *fn_args: P.args, **fn_kwargs: P.kwargs) -> T:
1489
+ return self.__wrapper(self.__instance, *fn_args, **fn_kwargs)
1490
+
1491
+
1492
+ def _import_a_sync():
1493
+ global a_sync
1494
+ from a_sync import a_sync
1495
+
1496
+
1497
+ __all__ = ["future", "ASyncFuture"]