Skip to Content
Utilities

Utilities

zwylib.SingletonMeta

class SingletonMeta(type)

Metaclass implementing the singleton pattern. Use it as the metaclass for any class that must have only one instance.

Example

class MyManager(metaclass=SingletonMeta): ... a = MyManager() b = MyManager() assert a is b # True

zwylib.Callback1

zwylib.Callback1(fn: (Any) -> None)

Wrapper class allowing a Python function to be passed into Java code via Chaquopy, emulating the Utilities.Callback Java interface.

Constructor Arguments

  • fn ((Any) -> None): A Python function that accepts a single argument and returns nothing. Called from Java via .run(...).

Methods

run

Callback1.run(arg: Any) -> None

Called from Java, forwards the provided argument to the Python function. Exceptions are logged internally and not raised.

Example

def my_python_callback(value): print(f"Received from Java: {value}") callback = zwylib.Callback1(my_python_callback) some_java_object.setCallback(callback)

zwylib.PyRunnable

zwylib.PyRunnable(fn: () -> None)

Wrapper class allowing a no-argument Python function to be passed into Java code as a java.lang.Runnable. Useful for Java setters that expect a Runnable callback (e.g. setOnDismissListener).

Constructor Arguments

  • fn (() -> None): A Python function that accepts no arguments and returns nothing. Called from Java via .run().

Methods

run

PyRunnable.run() -> None

Called from Java, invokes the wrapped Python function. Exceptions are logged internally and not raised.

Example

def on_dismiss(): print("Dismissed!") sheet.setOnDismissListener(zwylib.PyRunnable(on_dismiss))

Java Interop Helpers

zwylib.iterable_to_arraylist

zwylib.iterable_to_arraylist( iterable: Optional[Iterable[Any]], int_auto_convert=True ) -> Optional[ArrayList]

Converts any Python iterable to a Java ArrayList, optionally auto-converting Python integers to Java jint to avoid overflow/type mismatches.

Arguments

  • iterable (Optional[Iterable[Any]]): The iterable to convert. If None, returns None.
  • int_auto_convert (bool, default True): If True, converts Python int values to Java jint when adding to the ArrayList (falling back to a plain add on overflow).

Returns

  • Optional[ArrayList]: A Java ArrayList containing the elements of the input iterable, or None if the input is None.

Example

java_array = zwylib.iterable_to_arraylist([1, "item2"]) # java_array contains [jint(1), "item2"]

zwylib.arraylist_to_list

zwylib.arraylist_to_list(j_array_list: Optional[ArrayList]) -> Optional[List]

Converts a Java ArrayList to a Python list.

Arguments

  • j_array_list (Optional[ArrayList]): The Java ArrayList to convert. If None, returns None.

Returns

  • Optional[List]: A Python list containing the elements of the ArrayList, or None if the input is None.

Example

java_array = ArrayList() java_array.add("item1") java_array.add("item2") python_list = zwylib.arraylist_to_list(java_array) # python_list is ["item1", "item2"]

zwylib.list_to_arraylist

zwylib.list_to_arraylist(python_list: Optional[List], int_auto_convert=True)

Deprecated: Use iterable_to_arraylist instead.

Kept for backward compatibility — internally delegates to iterable_to_arraylist. Calling it emits a deprecation warning.

Exception Formatting

zwylib.format_exc

zwylib.format_exc() -> str

Formats the current exception traceback as a string, similar to traceback.format_exc().

Returns

  • str: A string containing the formatted traceback of the current exception, stripped of leading/trailing whitespace.

Example

try: 1 / 0 except ZeroDivisionError: error_trace = zwylib.format_exc() print(error_trace) # Prints the formatted traceback

zwylib.format_exc_from

zwylib.format_exc_from(e: Exception) -> str

Formats the full traceback of a specific exception as a string.

Arguments

  • e (Exception): The exception whose traceback should be formatted.

Returns

  • str: A string containing the formatted traceback of the exception, stripped of leading/trailing whitespace.

Example

try: 1 / 0 except ZeroDivisionError as e: error_trace = zwylib.format_exc_from(e) print(error_trace) # Prints the formatted traceback

zwylib.format_exc_only

zwylib.format_exc_only(e: Exception) -> str

Formats only the exception message and type (without the full traceback) as a string.

Arguments

  • e (Exception): The exception whose message and type should be formatted.

Returns

  • str: A string containing the formatted exception message and type, stripped of leading/trailing whitespace.

Example

try: 1 / 0 except ZeroDivisionError as e: error_msg = zwylib.format_exc_only(e) print(error_msg) # Prints: ZeroDivisionError: division by zero

Version Checks

zwylib.is_zwylib_version_sufficient

zwylib.is_zwylib_version_sufficient( plugin_name: str, version: str, notify: bool = True ) -> bool

Checks whether the current ZwyLib version is greater than or equal to the required version. If the version is insufficient and notify is True, a bulletin is shown with a button allowing the user to navigate to the update.

Arguments

  • plugin_name (str): Plugin name shown in the bulletin.
  • version (str): Minimum required ZwyLib version.
  • notify (bool, default True): Whether to show a bulletin on version mismatch.

Returns

  • bool: True if current ZwyLib version is sufficient, False otherwise.

Example

zwylib.is_zwylib_version_sufficient("MyPlugin", "1.2.0")

zwylib.is_client_version_sufficient

zwylib.is_client_version_sufficient(version_to_compare: str) -> bool

Checks whether the current exteraGram client build is greater than or equal to version_to_compare. Returns False (and logs the error) if the comparison fails for any reason.

Arguments

  • version_to_compare (str): Minimum required client version.

Returns

  • bool: True if the current client version is sufficient, False otherwise.

Example

if not zwylib.is_client_version_sufficient("12.6.0"): bulletins.show_error("This plugin requires exteraGram 12.6.0 or newer.")

Helper Functions

zwylib.safe_func_call

zwylib.safe_func_call(func: Optional[Callable], args: Optional[List[Any]] = None) -> Any

Calls func with the given positional arguments, catching and logging any exception instead of letting it propagate. If func returns a coroutine, it’s automatically scheduled via zwylib.async_manager.run_task and the resulting Future is returned instead of the coroutine itself.

Arguments

  • func (Optional[Callable]): The function to call. If None, nothing happens.
  • args (Optional[List[Any]], default None): Positional arguments to pass to func.

Returns

  • Any: Whatever func returns (or the scheduled Future if it’s a coroutine function), or None if func is None or raised.

Example

zwylib.safe_func_call(on_finish_callback, [self])

zwylib.create_bundle

zwylib.create_bundle(args: Dict[str, Union[bool, int, str, float]]) -> Bundle

Builds an Android Bundle from a plain Python dict, automatically picking the right put* method based on each value’s type (int, bool, str, float). Keys whose value isn’t one of these types are silently skipped.

Arguments

  • args (Dict[str, Union[bool, int, str, float]]): Mapping of keys to values to put into the bundle.

Returns

  • Bundle: The populated Android Bundle.

Example

args = zwylib.create_bundle({"isAlwaysShare": True, "chatAddType": 2}) activity = GroupCreateActivity(args)

zwylib.open_message

zwylib.open_message(peer_id: int, msg_id: int, topic_id: Optional[int] = None) -> None

Opens a specific message in a chat, using the app’s currently active activity. Assumes the peer is already locally accessible (i.e. the app already has its access hash) — for chats/channels that might not be, use safe_open_message instead.

Arguments

  • peer_id (int): ID of the peer (chat or user) to open.
  • msg_id (int): ID of the message to scroll to.
  • topic_id (Optional[int], default None): ID of the topic containing the message, if applicable.

Example

zwylib.open_message(-12345, 67890)

zwylib.safe_open_message

zwylib.safe_open_message( peer_id: int, msg_id: int, topic_id=0, chat_username: Optional[str] = None ) -> None

Coroutine version of open_message that resolves the peer’s access hash first if it isn’t already known locally, using chat_username to look it up. This is what powers the bulletin *_with_post_redirect methods in InnerBulletinHelper.

Arguments

  • peer_id (int): ID of the peer (chat or user) to open.
  • msg_id (int): ID of the message to scroll to.
  • topic_id (int, default 0): ID of the topic containing the message, if applicable.
  • chat_username (Optional[str], default None): Username used to resolve the peer if its access hash isn’t known locally yet. If it’s needed but not provided, the function logs an error and does nothing.

Example

async def go_to_post(): await zwylib.safe_open_message(-12345, 67890, chat_username="somepublicchat") zwylib.async_manager.run_task(go_to_post())
Last updated on