Module server.asyncio_extensions
Some helper functions for common async tasks
Functions
async def map_suppress(func: Callable[[~T], Coroutine[Any, Any, Any]], iterable: Iterable[~T], logger: logging.Logger = <Logger server.asyncio_extensions (WARNING)>, msg: str = '')
def synchronized(*args)
-
Ensure that a function will only execute in serial.
Params
lock
: An instance of asyncio.Lock to use for synchronization.
def synchronizedmethod(*args)
-
Create a method that will be wrapped with an async lock.
Params
attrname
: The name of the lock attribute that will be used. If the attribute doesn't exist or is None, a lock will be created. The default is to use a value based on the decorated function name.
Classes
class AsyncLock (*args, **kwargs)
-
Base class for protocol classes.
Protocol classes are defined as::
class Proto(Protocol): def meth(self) -> int: ...
Such classes are primarily used with static type checkers that recognize structural subtyping (static duck-typing), for example::
class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type check
See PEP 544 for details. Protocol classes decorated with @typing.runtime_checkable act as simple-minded runtime protocols that check only the presence of given attributes, ignoring their type signatures. Protocol classes can be generic, they are defined as::
class GenProto(Protocol[T]): def meth(self) -> T: ...
Expand source code
class AsyncLock(Protocol, AsyncContextManager["AsyncLock"]): def locked(self) -> bool: ... async def acquire(self) -> bool: ... def release(self) -> None: ...
Ancestors
- typing.Protocol
- contextlib.AbstractAsyncContextManager
- typing.Generic
- abc.ABC
Methods
async def acquire(self) ‑> bool
def locked(self) ‑> bool
def release(self) ‑> None
class SpinLock (sleep_duration: float = 0.01)
-
An asyncio spinlock. The advantage of using this over asyncio.Lock is that it can be called accross multiple event loops at the cost of being less performant. As with any spinlock, it's best used in situations where concurrent access is unlikely.
Expand source code
class SpinLock(_ContextManagerMixin): """ An asyncio spinlock. The advantage of using this over asyncio.Lock is that it can be called accross multiple event loops at the cost of being less performant. As with any spinlock, it's best used in situations where concurrent access is unlikely. """ def __init__(self, sleep_duration: float = 0.01): self.sleep_duration = sleep_duration self._locked = False def __repr__(self) -> str: res = super().__repr__() extra = "locked" if self._locked else "unlocked" return f"<{res[1:-1]} [{extra}]>" def locked(self) -> bool: """Return True if lock is acquired.""" return self._locked async def acquire(self) -> bool: """ Sleeps repeatedly for sleep_duration until the lock is unlocked, then sets it to locked and returns True. """ while self._locked: await asyncio.sleep(self.sleep_duration) self._locked = True return True def release(self) -> None: """ When invoked on an unlocked lock, a RuntimeError is raised. """ if self._locked: self._locked = False else: raise RuntimeError("Lock is not acquired.")
Ancestors
- asyncio.locks._ContextManagerMixin
Methods
async def acquire(self) ‑> bool
-
Sleeps repeatedly for sleep_duration until the lock is unlocked, then sets it to locked and returns True.
def locked(self) ‑> bool
-
Return True if lock is acquired.
def release(self) ‑> None
-
When invoked on an unlocked lock, a RuntimeError is raised.