Documentation Index
Fetch the complete documentation index at: https://mintlify.com/alex-ber/AlexBerUtils/llms.txt
Use this file to discover all available pages before exploring further.
LockingProxy wraps an arbitrary object and intercepts every interaction with it—attribute access, method calls, iteration, item read/write, and context management—acquiring an RLock before each operation.
See the author’s article for an in-depth explanation of the design.
Quick start
lock is supplied, one is created automatically.
The object to wrap. Can be any Python object: a list, dict, callable, async generator, Pydantic model, etc.
An existing
RLock to use. If omitted, LockingDefaultLockMixin creates a new RLock() automatically.Mixin architecture
LockingProxy is assembled from composable mixins. Each mixin handles one category of interaction. You can build a lighter proxy by subclassing only the mixins you need.
LockingIterableMixin
Makes __iter__ thread-safe by returning a LockingIterator that acquires the lock on each call to __next__.
LockingAsyncIterableMixin
Makes __aiter__ thread-safe by returning a LockingAsyncIterator that acquires the lock (async with) on each __anext__.
LockingAccessMixin
Intercepts __getattr__ to wrap every attribute lookup:
- Regular methods are wrapped in a
synchronized_methodthat holds the lock for the duration of the call. - Coroutine methods are wrapped in an
asynchronized_methodthat holds the async lock (async with) while awaiting. - Properties / descriptors are accessed directly (no wrapping needed).
LockingCallableMixin
Intercepts __call__. If the wrapped object is a coroutine function, it is called inside async with self._lock; otherwise inside with self._lock.
LockingGetItemMixin
Provides thread-safe __getitem__ and __setitem__.
LockingSetItemMixin
Provides a thread-safe __setitem__ only (lighter alternative to LockingGetItemMixin when reads do not need protection).
SyncContextManagerMixin
Adds __enter__ / __exit__ that call self._lock.acquire() and self._lock.release(). Lets the proxy itself be used as a context manager.
AsyncContextManagerMixin
Adds __aenter__ / __aexit__ using self._lock.async_acquire() and self._lock.async_release().
LockingDefaultLockMixin
Checks whether a lock keyword argument was supplied. If not, it creates a new RLock() and injects it into kwargs before calling super().__init__. This is always included in LockingProxy.
Full class hierarchy
LockingProxy inherits from all the mixins above in this order:
__init__ is called exactly once via cooperative super().__init__(**kwargs).
