ion.utils

This module provides helper functions for configuration scripts. The non-obvious member is exec_generator(), which drives Python generators as coroutines on the compositor’s event loop - useful for animations and multi-step UI sequences that need to yield between steps.

Utility functions for spawning processes and file operations.

Classes

class ion.utils.GeneratorHandle

The generator exec_generator() runs, for the caller to ask whether it is still running, or to end it.

cancel(self)

End the generator as the compositor ends one on shutdown: send it an EventCancel, then close it if it yields again. Does nothing once it has finished.

A generator can’t cancel itself: it returns instead.

Raises:

RuntimeError – When called from the generator itself.

Return type:

None

pending

Whether the generator has not finished: True until it returns, raises or is cancelled.

Type:

bool

(readonly)

Special Methods
__repr__(self)
Return type:

str

Functions

ion.utils.error_report(context, exc)

Report an exception the way the compositor reports one it catches: logged with its traceback, and shown in a popup when ion.types.SystemPreferences.notify_on_error is set, unless it was just shown.

For a handler that catches an exception rather than letting it propagate, so the failure is not silent.

try:
    provider()
except Exception as ex:
    ion.utils.error_report("My provider", ex)
Parameters:
  • context (str) – What failed, leading the report.

  • exc (BaseException) – The exception.

Return type:

None

ion.utils.exec(argv)

Execute a command directly (no shell).

Arguments are passed as-is without shell quoting concerns, and one that isn’t valid UTF-8 as its real bytes, as shell() passes its command.

Parameters:

argv (tuple[str, ...]) – Program and arguments.

Returns:

True if the process was spawned, False on immediate failure.

Return type:

bool

ion.utils.exec_generator(callback)

Run a Python generator as a coroutine driven by the compositor’s event loop.

The generator is advanced one step at a time, with compositor state updates processed between yields. Yield GeneratorStep to control scheduling:

def my_sequence():
    ion.utils.log("step 1")
    yield GeneratorStep()  # Resume on next event-loop iteration.
    ion.utils.log("step 2")
    yield GeneratorStep(time=500)  # Wait 500 ms.
    ion.utils.log("step 3")
    event = yield GeneratorStep(consume_event=True)  # Wait for input.
    if isinstance(event, EventPointer):
        ion.utils.log("clicked!")

ion.utils.exec_generator(my_sequence())

Multiple generators can run at once, and one may start another:

  • consume_event is a global input mode, not a subscription. While any generator sets it, bindings and clients see no input, and every consuming generator receives each event.

  • The cursor stack (ion.wm.cursor_push()) and every skip_desktop_overlay reset only when the last generator ends. Release anything else in a try/finally, which also runs when a generator is cancelled.

  • Compositor state changes between yields, so check proxies with is_valid after each one.

  • ion.wm.context is set only before the first yield.

Parameters:

callback (Generator[GeneratorStep, Event, None]) – A generator object.

Returns:

A handle to the generator, for asking whether it still runs.

Return type:

GeneratorHandle

ion.utils.home()

User’s home directory.

Decoded as ion.app.config_dir() is.

Return type:

str

ion.utils.log(message)

Log a message from Python.

Parameters:

message (str) – The message to log.

Return type:

None

ion.utils.notify(message, title=None, urgency=None)

Send a desktop notification.

The notifier program is notify-send, overridable with the IONWL_NOTIFY_COMMAND environment variable (e.g. dunstify, or a wrapper); it receives the same [title] message [-u urgency] arguments.

Parameters:
  • message (str) – The notification body text.

  • title (str | None) – Optional notification title.

  • urgency (Literal['low', 'normal', 'critical'] | None) – Optional urgency level.

Return type:

None

ion.utils.shell(command)

Execute a shell command (spawn a detached process via sh -c).

Use this when the command string may contain shell features (pipes, redirects, variable expansion, etc.).

A path that isn’t valid UTF-8 (holding surrogateescape surrogates, as os.fsdecode gives) reaches the shell as its real bytes.

Parameters:

command (str) – Shell command to execute.

Returns:

True if the process was spawned, False on immediate failure.

Return type:

bool