Event Loops

Event loops are the heart of Simpleline. Every event loop is based on the AbstractEventLoop, and they all work with signals. A signal is a message passed to the loop containing some information. Signals are passed to an event loop by calling AbstractEventLoop.enqueue_signal(). These signals are then processed by calling AbstractEventLoop.process_signals(). This method can be called by an application developer manually or by the AbstractEventLoop.run() method, which is called by App.run() to start the Simpleline-based application. When a signal is processed, all handlers attached to this signal are called. Signal handler assignment is done by the AbstractEventLoop.register_signal_handler() method.

Event loops can also be started recursively by AbstractEventLoop.execute_new_loop(). The old event loop is waiting for this event loop to stop. New loop execution is mandatory for modal screens to work, since they can’t be interrupted by other screens. This new event loop is terminated by closing the last screen in the event loop or by calling the AbstractEventLoop.close_loop() method.

The last event loop should be terminated by closing the last screen in the screen stack or by calling AbstractEventLoop.close_loop(). In case a fatal error occurs the AbstractEventLoop.force_quit() method can be used to immediately kill the loop.

If a reaction on quitting the application (closing the last event loop) is required, the quit callback can be used. The quit callback can be set by the AbstractEventLoop.set_quit_callback() method.

The following event loops are supported by Simpleline, but you can also Create your own loop :

Main Loop

The main loop is the default event loop for Simpleline projects. The benefit of using MainLoop is that it isn’t necessary to have any dependencies on other libraries. It is a lightweight event loop implemented completely in Python.

class simpleline.event_loop.main_loop.MainLoop

Bases: simpleline.event_loop.AbstractEventLoop

Default main event loop for the Simpleline.

This event loop can be replaced by your event loop by implementing simpleline.event_loop.AbstractEventLoop class.

close_loop()

Close active event loop.

Close an event loop created by the execute_new_loop() method.

enqueue_signal(signal)

Enqueue new event for processing.

Enqueue signal to the most inner queue (nearest to the active queue) where the signal.source belongs. If it belongs nowhere enqueue it to the active one.

This method is thread safe.

Parameters:signal (Instance based on AbstractEvent class.) – Event which you want to add to the event queue for processing.
execute_new_loop(signal)

Starts the new event loop and pass signal in it.

This is required for processing a modal screens.

Parameters:signal (The AbstractSignal based class.) – Signal passed to the new event loop.
force_quit()

Force quit all running event loops.

Kill all loop including inner loops (modal window). None of the Simpleline events will be processed anymore.

kill_app_with_traceback(exception_signal, data=None)

Print exception and screen stack and kill the application.

Parameters:
  • exception_signal (Instance of simpleline.event_loop.signals.ExceptionSignal class.) – ExceptionSignal encapsulating the original exception which will be passed to the sys.excepthook method.
  • data (Anything will be ignored.) – To be usable as signal handler.
process_signals(return_after=None)

This method processes incoming async messages.

Process signals en-queued by the self.enqueue_signal() method. Call handlers registered to the signals by the self.register_signal_handler() method.

When return_after is specified then wait to the point when this signal is processed. NO warranty that this method will return immediately after the signal was processed!

Without return_after parameter this method will return after all queued signals with the highest priority will be processed.

The method is NOT thread safe!

Parameters:return_after (Class of the signal.) – Wait on this signal to be processed.
register_signal_handler(signal, callback, data=None)

Register a callback which will be called when message “event” is encountered during process_events.

The callback has to accept two arguments: - the received message in the form of (type, [arguments]) - the data registered with the handler

Parameters:
  • signal (Class based on the simpleline.event_loop.AbstractSignal class.) – Signal class we want to react on.
  • callback (func(event_message, data)) – The callback function.
  • data (Anything.) – Optional data to pass to callback.
register_signal_source(signal_source)

Register source of signal for actual event queue.

Parameters:signal_source (simpleline.render.ui_screen.UIScreen.) – Source for future signals.
run()

This methods starts the application.

Do not use self.mainloop() directly as run() handles all the required exceptions needed to keep nested mainloop working.

set_quit_callback(callback, args=None)

Call this callback when event loop quits.

Parameters:
  • callback (Function with one parameter data func(data).) – Call this callback when event loops ends (application quit).
  • args (Anything.) – Arguments passed to the quit callback.

GLib Event loop

The GLib event loop was added in order to utilize existing event loops used by other libraries, for example, DBus connections. Simpleline with this loop should have the same behavior as with the Main Loop.

To use this loop you need to set it via the App class:

# Create Glib event loop.
glib_loop = GLibEventLoop()

# Use glib event loop instead of the original one.
# Everything else should behave the same as with the original Simpleline loop.
App.initialize(event_loop=glib_loop)

The GLib loop can be accessed by the GLibEventLoop.active_main_loop property, or by getting the default loop from GLib directly GLib.MainLoop().

class simpleline.event_loop.glib_event_loop.GLibEventLoop

Bases: simpleline.event_loop.AbstractEventLoop

active_main_loop

Return GLib mainloop object.

close_loop()

Close active event loop.

Close an event loop created by the execute_new_loop() method.

enqueue_signal(signal)

Enqueue new event for processing.

Parameters:signal (instance based on AbstractEvent class) – signal which you want to add to the event queue for processing
execute_new_loop(signal)

Starts the new event loop and pass signal in it.

This is required for processing a modal screens.

Parameters:signal (AbstractSignal based class) – signal passed to the new event loop
force_quit()

Force quit all running event loops.

Kill all loop including inner loops (modal window). None of the Simpleline events will be processed anymore.

kill_app_with_traceback(exception_signal, data=None)

Print exception and screen stack and kill the application.

Parameters:
  • exception_signal (Instance of simpleline.event_loop.signals.ExceptionSignal class.) – ExceptionSignal encapsulating the original exception which will be passed to the sys.excepthook method.
  • data (Anything will be ignored.) – To be usable as signal handler.
process_signals(return_after=None)

This method processes incoming async messages.

Process signals en-queued by the self.enqueue_signal() method. Call handlers registered
to the signals by the self.register_signal_handler() method.

When return_after is specified then wait to the point when this signal is processed. NO warranty that this method will return immediately after the signal was processed!

Without return_after parameter this method will return after all queued signals with the highest priority will be processed.

The method is NOT thread safe!

Parameters:return_after (Class of the signal.) – Wait on this signal to be processed.
register_signal_handler(signal, callback, data=None)

Register a callback which will be called when message “event” is encountered during process_events.

The callback has to accept two arguments: - the received message in the form of (type, [arguments]) - the data registered with the handler

Parameters:
  • signal (Class based on the simpleline.event_loop.AbstractSignal class.) – Signal class we want to react on.
  • callback (func(event_message, data)) – The callback function.
  • data (Anything.) – Optional data to pass to callback.
register_signal_source(signal_source)

Register source of signal for actual event queue.

Parameters:signal_source (simpleline.render.ui_screen.UIScreen) – Source for future signals.
run()

Starts the event loop.

set_quit_callback(callback, args=None)

Call this callback when event loop quits.

Parameters:
  • callback (Function with one parameter data func(data).) – Call this callback when event loops ends (application quit).
  • args (Anything.) – Arguments passed to the quit callback.

Create your own loop

If new loop support is required, it should inherit from AbstractEventLoop and implement the same behavior as the Main Loop. You can use existing tests from the event loops to start. If the new loop is stable enough, pull requests are always welcome at Simpleline repository.

class simpleline.event_loop.AbstractEventLoop
close_loop()

Close active event loop.

Close an event loop created by the execute_new_loop() method.

enqueue_signal(signal)

Enqueue new event for processing.

Parameters:signal (Instance based on AbstractEvent class.) – Signal which you want to add to the event queue for processing.
execute_new_loop(signal)

Starts the new event loop and pass signal in it.

This is required for processing a modal screens.

Parameters:signal (The AbstractSignal based class.) – Signal passed to the new event loop.
force_quit()

Force quit all running event loops.

Kill all loop including inner loops (modal window). None of the Simpleline events will be processed anymore.

kill_app_with_traceback(exception_signal, data=None)

Print exception and screen stack and kill the application.

Parameters:
  • exception_signal (Instance of simpleline.event_loop.signals.ExceptionSignal class.) – ExceptionSignal encapsulating the original exception which will be passed to the sys.excepthook method.
  • data (Anything will be ignored.) – To be usable as signal handler.
process_signals(return_after=None)

This method processes incoming async messages.

Process signals enqueued by the self.enqueue_signal() method. Call handlers registered to the signals by the self.register_signal_handler() method.

When return_after is specified then wait to the point when this signal is processed. NO warranty that this method will return immediately after the signal was processed!

Without return_after parameter this method will return after all queued signals with the highest priority will be processed.

The method is NOT thread safe!

Parameters:return_after (Class of the signal.) – Wait on this signal to be processed.
register_signal_handler(signal, callback, data=None)

Register a callback which will be called when message “event” is encountered during process_events.

The callback has to accept two arguments: - the received message in the form of (type, [arguments]) - the data registered with the handler

Parameters:
  • signal (Class based on the simpleline.event_loop.AbstractSignal class.) – Signal class we want to react on.
  • callback (func(event_message, data)) – The callback function.
  • data (Anything.) – Optional data to pass to callback.
register_signal_source(signal_source)

Register source of signal for actual event queue.

Parameters:signal_source (simpleline.render.ui_screen.UIScreen) – Source for future signals.
run()

Starts the event loop.

set_quit_callback(callback, args=None)

Call this callback when event loop quits.

Parameters:
  • callback (Function with one parameter data func(data).) – Call this callback when event loops ends (application quit).
  • args (Anything.) – Arguments passed to the quit callback.