Async
ZwyLib runs a dedicated background thread with its own asyncio event loop, so plugins can use coroutines without blocking the UI thread or setting up their own loop/thread management. Most of ZwyLib’s own async features (Requests, async commands, the dialog pickers and input dialogs) are built on top of it.
Getting Started
# ... metadata and zwylib import ...
from zwylib import async_manager, Requests
async def do_something(peer_id: int):
response = await Requests.get_message(peer_id, 1)
print(response)
class MyPlugin(BasePlugin):
def on_send_message_hook(self, account, params) -> HookResult:
async_manager.run_task(do_something(params.peer))
return HookResult()zwylib.AsyncManager
zwylib.async_manager: AsyncManagerThis global object is created during ZwyLib initialization and manages a single background thread/event loop shared by all plugins. You should only use its documented methods and the loop property.
Properties
loop: AbstractEventLoop
The event loop running on ZwyLib’s background thread. Useful for creating your own Futures (async_manager.loop.create_future()) or scheduling thread-safe callbacks (async_manager.loop.call_soon_threadsafe(...)) when integrating with Java callback-based APIs.
Methods
run_task
AsyncManager.run_task(coro: Coroutine) -> FutureSchedules a coroutine to run on the background event loop and returns a Future representing it. Starts the background thread on first use. The task is tracked under the calling plugin’s ID so it can be cancelled later via cancel_all_tasks or cancel_all_for — ZwyLib also cancels all of a plugin’s tasks automatically when it’s unloaded. Unhandled exceptions inside the coroutine are caught and logged rather than raised.
Parameters
coro(Coroutine): The coroutine to run.
Example
async def fetch_and_log(peer_id: int):
msg = await Requests.get_message(peer_id, 1)
print(msg)
async_manager.run_task(fetch_and_log(-12345))cancel_all_tasks
AsyncManager.cancel_all_tasks() -> NoneCancels all currently running tasks belonging to the calling plugin. Shorthand for cancel_all_for with the plugin ID inferred from the call stack.
cancel_all_for
AsyncManager.cancel_all_for(plugin_id: str) -> NoneCancels all currently running tasks belonging to the given plugin.
Parameters
plugin_id(str): ID of the plugin whose tasks should be cancelled.
Example
async_manager.cancel_all_for(__id__)as_callback
AsyncManager.as_callback(
callback_obj: Any,
success: str,
error: Optional[str] = None
) -> _AsyncMarkerMarks a Java object as the target of a callback-based API call, for use with wrap_java_call. ZwyLib will temporarily wrap callback_obj’s success (and optionally error) methods so that calling either resolves a Future, without losing the object’s original behavior (the original methods are still invoked first).
Parameters
callback_obj(Any): The Java delegate/listener object that will receive the callback.success(str): Name of the method oncallback_objthat signals success.error(Optional[str], defaultNone): Name of the method oncallback_objthat signals failure, if any.
Example
marker = async_manager.as_callback(my_delegate, "onSuccess", "onError")wrap_java_call
AsyncManager.wrap_java_call(java_method: Callable, *args, **kwargs) -> AnyCoroutine that calls a Java method which reports its result through a callback object, and awaits that callback instead of the method’s own (synchronous) return value. Exactly one of args should be a marker produced by as_callback — it’s swapped in for the underlying Java object before the call.
Parameters
java_method(Callable): The Java method to call.*args,**kwargs: Arguments to pass tojava_method. One positional argument should be anas_callback(...)marker.
Example
async def pick_something():
marker = async_manager.as_callback(delegate, "onSuccess", "onError")
return await async_manager.wrap_java_call(some_activity.doSomethingAsync, marker)