API reference

Converter

unblock.asyncify(obj: _ClassT) _ClassT
unblock.asyncify(obj: _ClassT, *, executor: Executor | Literal['thread', 'process'] = 'thread', include: object = None, exclude: object = None) _ClassT
unblock.asyncify(obj: Callable[[_P], _T]) Callable[[_P], Awaitable[_T]]
unblock.asyncify(obj: Callable[[_P], _T], *, executor: Executor | Literal['thread', 'process'] = 'thread') Callable[[_P], Awaitable[_T]]
unblock.asyncify(obj: None = None, *, executor: Executor | Literal['thread', 'process'] = 'thread', include: object = None, exclude: object = None) Callable[[Callable[[_P], _T]], Callable[[_P], Awaitable[_T]]]

Convert a synchronous callable or class to its asynchronous form.

Usage forms:

  • @asyncify on a function or method -> an async version (thread pool).

  • @asyncify(executor="process") -> runs on the process pool. Works as a decorator on any importable (module-level) function; closures, lambdas, and locally-defined functions are rejected with UnblockError.

  • @asyncify / @asyncify(include=..., exclude=...) on a class -> asyncify selected methods in place and auto-add async iterator / context-manager protocol methods (see unblock.classes).

  • asyncify(fn) -> the direct-call form, equivalent to the decorator.

Parameters:
  • obj – The function, method, class, or None (parameterized form).

  • executor"thread" (default), "process", or a concrete concurrent.futures.Executor instance.

  • include – Class use only – asyncify exactly these method names.

  • exclude – Class use only – asyncify all public methods except these.

Returns:

For a callable, a wrapper returning an awaitable; for a class, the same class with methods asyncified; for None, a configured decorator.

Raises:

UnblockError – if obj is not a function, method, or class; if include/exclude are given for a non-class; or if a process executor is requested for an unpicklable callable.

Note

Cancelling the returned awaitable cannot forcibly stop work that has already started in a thread or process (standard asyncio.loop.run_in_executor() behaviour). Already-async functions are returned unchanged.

Properties

class unblock.async_property(fget: Callable[[Any], _T] | None = None, *, executor: Executor | Literal['thread', 'process'] = 'thread')

An asynchronous, non-cached property.

Usage:

class C:
    @async_property
    def value(self):
        return compute()

await C().value

The getter runs on the configured executor every time the property is awaited, so it always reflects current state.

class unblock.async_cached_property(fget: Callable[[Any], _T] | None = None, *, executor: Executor | Literal['thread', 'process'] = 'thread')

An asynchronous property whose value is computed once and cached.

Usage:

class C:
    @async_cached_property
    def value(self):
        return expensive()

c = C()
await c.value  # computes
await c.value  # returns the cached value

The getter runs at most once per instance, even if the property is awaited concurrently (a per-instance lock serializes the first computation). Assigning to the attribute overrides the cache; del clears it.

Mixins

class unblock.AsyncMixin

Wrap a base class’s public methods; auto-detect iterator/context protocols.

Usage:

class Wrapper(MyClass, AsyncMixin, executor="process"):
    pass
class unblock.AsyncIterMixin

Like AsyncMixin, and provide async iteration over a sync iterator.

class unblock.AsyncContextMixin

Like AsyncMixin, and provide an async context manager.

Works even when the wrapped class is not a real context manager but exposes a close() method.

class unblock.AsyncContextIterMixin

Combine async iteration and async context management.

Configuration and lifecycle

unblock.set_thread_pool(executor: ThreadPoolExecutor) None

Replace the shared thread pool with executor.

Raises:

UnblockError – if executor is not a concurrent.futures.ThreadPoolExecutor.

unblock.set_process_pool(executor: ProcessPoolExecutor) None

Replace the shared process pool with executor.

Raises:

UnblockError – if executor is not a concurrent.futures.ProcessPoolExecutor.

unblock.shutdown(wait: bool = True) None

Shut down any pools unblock created and mark the library shut down.

Idempotent and safe to call when nothing was ever created. After shutdown, requesting a default pool raises UnblockError until a new pool is supplied via set_thread_pool() / set_process_pool().

This is registered with atexit, so default pools are cleaned up on interpreter exit without any action from the caller.

Errors

exception unblock.UnblockError

Raised when unblock is misused or cannot honour a request.

Common situations:

  • unblock.asyncify() is given something it cannot convert (not a function, method, or class).

  • An invalid executor is supplied to the configuration helpers or to the executor argument (anything other than "thread", "process", or a concurrent.futures.Executor instance).

  • A callable that cannot be pickled (a closure, lambda, or locally defined function) is asyncified for the process pool.

  • An executor is requested after unblock.shutdown() has been called.