Source code for asyncutils.futures

 1# ty: ignore[unresolved-import]
 2__lazy_modules__ = frozenset(('_contextvars',))
 3from asyncutils._internal.helpers import copy_and_clear, fullname
 4from asyncutils._internal.submodules import futures_all as __all__
 5from _contextvars import copy_context
 6from asyncio.futures import Future, _PyFuture
 7from asyncio.tasks import Task, _PyTask, eager_task_factory
 8from sys import audit
 9class FB:
10    def __init__(self): self._creation_time = self.get_loop().time() # ty: ignore[unresolved-attribute]
11    def __lt__(self, other, /): return self._creation_time < other._creation_time
[docs] 12class TimeAwareFuture(FB, Future): ...
[docs] 13class TimeAwareTask(FB, Task): ...
14def ff(a): 15 def remove_callback(self, fn, /): 16 if r := len(C := getattr(self, a))-len(l := [(f, c) for f, c in C if f is not fn]): C[:] = l 17 return r 18 return remove_callback
[docs] 19class AsyncCallbacksFuture(_PyFuture): 20 def __init__(self, *, loop=None): _PyFuture.__init__(self, loop=loop); self._setup() 21 def _setup(self): self._async_callbacks, self._noargs_callbacks, self._noargs_async_callbacks = [], [], []
[docs] 22 def add_async_callback(self, fn, /, *, context=None): 23 if self._state == 'PENDING': self._async_callbacks.append((fn, context or copy_context())) 24 else: self._loop.create_task(fn(self))
[docs] 25 def add_noargs_callback(self, fn, /, *, context=None): 26 if self._state == 'PENDING': self._noargs_callbacks.append((fn, context or copy_context())) 27 else: self._loop.call_soon(fn)
[docs] 28 def add_noargs_async_callback(self, fn, /, *, context=None): 29 if self._state == 'PENDING': self._noargs_async_callbacks.append((fn, context or copy_context())) 30 else: self._loop.create_task(fn())
31 remove_async_callback, remove_noargs_callback, remove_noargs_async_callback = map(ff, ('_async_callbacks', '_noargs_callbacks', '_noargs_async_callbacks')) 32 def __schedule_callbacks(self): 33 audit(f'{fullname(self)}/schedule_callbacks', id(self)); a, b = (l := self._loop).create_task, l.call_soon; c, d, e, f = map(copy_and_clear, (self._async_callbacks, self._callbacks, self._noargs_async_callbacks, self._noargs_callbacks)) 34 for g, _ in c: a(g(self), context=_) 35 for g, _ in d: b(g, self, context=_) 36 for g, _ in e: a(g(), context=_) 37 for g, _ in f: b(g, context=_)
[docs] 38class AsyncCallbacksTask(_PyTask, AsyncCallbacksFuture): # ty: ignore[inconsistent-mro] 39 def __init__(self, coro, **k): _PyTask.__init__(self, coro, **k); self._setup()
[docs] 40class EagerAsyncCallbacksFuture(AsyncCallbacksFuture): 41 def _setup(self): self._loop.set_task_factory(eager_task_factory); super()._setup()
[docs] 42class EagerAsyncCallbacksTask(AsyncCallbacksTask, EagerAsyncCallbacksFuture): ...
[docs] 43class TimeAwareAsyncCallbacksFuture(FB, AsyncCallbacksFuture): ...
[docs] 44class TimeAwareAsyncCallbacksTask(FB, AsyncCallbacksTask): ...
[docs] 45class EagerTimeAwareAsyncCallbacksFuture(TimeAwareAsyncCallbacksFuture, EagerAsyncCallbacksFuture): ...
[docs] 46class EagerTimeAwareAsyncCallbacksTask(TimeAwareAsyncCallbacksTask, EagerAsyncCallbacksTask): ...
47del FB, ff