Helpers

These are various objects and functions that help you with general-purpose tasks while building your application - for example, config management, running initialization tasks or exiting event loops on a keypress. They can help you build the logic of your application quicker, and allow to not repeat the code that was already written for other ZPUI apps.

local_path_gen helper

helpers.local_path_gen(_name_)[source]

This function generates a local_path function you can use in your scripts to get an absolute path to a file in your app’s directory. You need to pass __name__ to local_path_gen. Example usage:

from helpers import local_path_gen
local_path = local_path_gen(__name__)
...
config_path = local_path("config.json")

The resulting local_path function supports multiple arguments, passing all of them to os.path.join internally.

ExitHelper

class helpers.ExitHelper(i, keys=['KEY_LEFT'], cb=None)[source]

A simple helper for loops, to allow exiting them on pressing KEY_LEFT (or other keys).

You need to make sure that, while the loop is running, no other UI element sets its callbacks. with Printer UI elements, you can usually pass None instead of i to achieve that.

Arguments:

  • i: input device
  • keys: all the keys that should trigger an exit
  • cb: the callback that should be executed once one of the keys is pressed. By default, sets an internal flag that you can check with do_exit and do_run.
start()[source]

Clears input device keymap, registers callbacks and enables input listener.

do_exit()[source]

Returns True once exit flag has been set, False otherwise.

do_run()[source]

Returns False once exit flag has been set, True otherwise.

reset()[source]

Clears the exit flag.

stop()[source]

Stop input listener and remove the created keymap. Shouldn’t usually be necessary, since all other UI elements are supposed to make sure their callbacks are set.

Usage:

from helpers import ExitHelper
...
eh = ExitHelper(i)
eh.start()
while eh.do_run():
    ... #do something until the user presses KEY_LEFT

There is also a shortened usage form:

...
eh = ExitHelper(i).start()
while eh.do_run():
    ... #do your thing

Oneshot helper

class helpers.Oneshot(func, *args, **kwargs)[source]

Oneshot runner for callables. Each instance of Oneshot will only run once, unless reset. You can query on whether the runner has finished, and whether it’s still running.

Args:

  • func: callable to be run
  • *args: positional arguments for the callable
  • **kwargs: keyword arguments for the callable
run()[source]

Run the callable. Sets the running and finished attributes as the function progresses. This function doesn’t handle exceptions. Passes the return value through.

reset()[source]

Resets all flags, allowing the callable to be run once again. Will raise an Exception if the callable is still running.

running

Shows whether the callable is still running after it has been launched (assuming it has been launched).

finished

Shows whether the callable has finished running after it has been launched (assuming it has been launched).

Usage:

from helpers import Oneshot
...
def init_hardware():
    #can only be run once

#since oneshot is only defined once, init_hardware function will only be run once,
#unless oneshot is reset.
oneshot = Oneshot(init_hardware)

def callback():
    oneshot.run() #something that you can't or don't want to init in init_app
    ... #do whatever you want to do

BackgroundRunner helper

class helpers.BackgroundRunner(func, *args, **kwargs)[source]

Background runner for callables. Once launched, it’ll run in background until it’s done.. You can query on whether the runner has finished, and whether it’s still running.

Args:

  • func: function to be run
  • *args: positional arguments for the function
  • **kwargs: keyword arguments for the function
running

Shows whether the callable is still running after it has been launched (assuming it has been launched).

finished

Shows whether the callable has finished running after it has been launched (assuming it has been launched).

failed

Shows whether the callable has thrown an exception during execution (assuming it has been launched). The exception info will be stored in self.exc_info.

threaded_runner(print_exc=True)[source]

Actually runs the callable. Sets the running and finished attributes as the callable progresses. This method catches exceptions, stores sys.exc_info in self.exc_info, unsets self.running and re-raises the exception. Function’s return value is stored as self.return_value.

Not to be called directly!

run(daemonize=True)[source]

Starts a thread that will run the callable.

reset()[source]

Resets all flags, restoring a clean state of the runner.

Usage:

from helpers import BackgroundRunner
...
def init_hardware():
    #takes a long time

init = BackgroundRunner(init_hardware)

def init_app(i, o):
    ...
    init.run() #something too long that just has to run in the background,
    #so that app is loaded quickly, but still can be initialized.

def callback():
    if init.running: #still hasn't finished
        PrettyPrinter("Still initializing...", i, o)
        return
    elif init.failed: #finished but threw an exception
        PrettyPrinter("Hardware initialization failed!", i, o)
        return
    ... #everything initialized, can proceed safely

Combining BackgroundRunner and Oneshot

from helpers import BackgroundRunner, Oneshot
...
def init_hardware():
    #takes a long time, *and* can only be run once

init = BackgroundRunner(Oneshot(init_hardware).run)

def init_app(i, o):
    #for some reason, you can't put the initialization here
    #maybe that'll lock the device and you want to make sure
    #that other apps can use this until your app started to use it.

def callback():
    init.run()
    #BackgroundRunner might have already ran
    #but Oneshot inside won't run more than once
    if init.running: #still hasn't finished
        PrettyPrinter("Still initializing, please wait...", i, o)
        eh = ExitHelper(i).start()
        while eh.do_run() and init.running:
            sleep(0.1)
        if eh.do_exit(): return #User left impatiently before init has finished
        #Even if the user has left, the hardware_init will continue running
    elif init.failed: #finished but threw an exception
        PrettyPrinter("Hardware initialization failed!", i, o)
        return
    ... #everything initialized, can proceed safely