Managers¶
Managers manage displaying panels and retrieving user input, so you don’t have to worry about it. Your code just needs to tell the manager what you want to display and watch for messages back from the manager containing input from the user.
- thurible.queued_manager(q_to: Queue, q_from: Queue, term: Terminal | None = None, displays: dict | None = None) None[source]¶
Manage a terminal display by sending and receiving
thurible.messages.Messageobjects throughqueue.Queueobjects.Warning
thurible.queued_manager()is intended to be run in its own thread or process. If you try to run it synchronously with the rest of your application, the loop will prevent your application from completing execution. This is why it is a “queued” manager.- Parameters:
q_to – A queue for messages the program sends to the manager.
q_from – A queue for messages the manager sends to the program.
term – An instance of blessed.Terminal used to interact with the terminal.
displays – (Optional.) Storage for the panels the program may want the manager to display.
- Returns:
None.
- Return type:
NoneType
- Usage:
>>> from queue import Queue >>> from threading import Thread >>> from thurible import get_terminal, queued_manager >>> from thurible.messages import End >>> >>> # Create a queue to send messages to the manager. >>> q_in = Queue() >>> >>> # Create a queue to receive messages from the manager. >>> q_out = Queue() >>> >>> # Get a terminal instance for the manager to use. >>> term = get_terminal() >>> >>> # Run the manager in a separate thread. >>> T = Thread(target=queued_manager, args=(q_in, q_out, term)) >>> T.start() >>> >>> # End the thread running the queued_manager. >>> msg = End('Ending.') >>> q_in.put(msg)
- thurible.event_manager(event_map: Mapping[type, Callable[[Message, Queue], bool]] | None = None, initial_panel: Panel | None = None) None[source]¶
Manage a terminal display by mapping Response Messages to event scripts (see below).
- Parameters:
event_map – (Optional.) A
dictmapping thethurible.panel.Messagetypes managers can send to applications (Response Messages) to functions in your application. These functions must accept aqueue.Queueobject and the response message as parameters. It must return aboolindicating whether the application should continue running.initial_panel – (Optional.) The first panel displayed in the terminal. While this is technically optional, that’s just for testing purposes. You should really provide this to the manager. The panel passed this way will be stored as “__init”.
- Returns:
None
- Return type:
NoneType
- Usage:
An example small application that uses the
thurible.event_manager()show a splash screen then quit if a button is pressed:from thurible import event_manager, Splash import thurible.messages as tm # Create the event handlers. def data_handler(msg, q_to): msg = tm.End('Quitting.') q_to.put(msg) return False def ending_handler(msg, q_to): if msg.exception: raise msg.exception return False # Map the handlers to event messages. event_map = { tm.Data: data_handler, tm.Ending: ending_handler, } # Create the panel to display when the manager starts. splash = Splash('SPAM!') # Run the event_manager. event_manager(event_map, splash)
- Event scripts:
An event script is a function that:
Accepts a response message it will receive from the manager and a
queue.Queuefor it to send command messages to the manager.Returns True if the manager should continue running.
Returns False if the manager should end.
For example, let’s say we want an event script that will handle user input. It will:
Display a splash screen if the user presses x,
Display a different splash screen if the user presses y,
End the
event_manager()if the user presses the space bar.
That would look like:
import thurible from thurible import messages as msgs def data_handler(data, q_to): keep_running = True # If the user presses `x` display the X screen. if data.value == 'x': splash = thurible.Splash('XXXXX') store_msg = msgs.Store('x', splash) q_to.put(store_msg) show_msg = msgs.Show('x') q_to.put(show_msg) # If the user presses `y` display the Y screen. if data.value == 'y': splash = thurible.Splash('YYYYY') store_msg = msgs.Store('y', splash) q_to.put(store_msg) show_msg = msgs.Show('y') q_to.put(show_msg) # If the user presses ` ` end. if data.value == ' ': keep_running = False return keep_running
These event scripts are intended for fairly simple use cases. They respond to a single message from the manager. They can add messages to the manager’s input queue to tell the manager to act. They can tell the manager to end.
If you need more complex behaviors like checking the manager’s state or maintaining internal state, you probably should use
queued_manager()directly rather thanevent_manager().
How Managers Work¶
The following are details on the internal operations of managers to
help you understand how to work with them. While they apply to both
managers, these details are mostly hidden from event_manager().
It’s more important to understand them when working with
queued_manager().
The Manager Loop¶
Once started, a manager loops through a standard set of actions until it is told to close or crashes. Those actions are:
Check for a message from the application.
If there was a comand message, perform the commanded action.
If the commanded action should return a response to the application, send that response.
If there is no action for the command message received, send that message to the
Panel.update()of the currently displayed panel.
Check for a key press from the user.
If there was a key press, send the
blessed.keyboard.Keystrokeobject to thePanel.action()of the currently displayed panel.If the
Panel.action()returns data, send that data to the application in athurible.messages.Datamessage.If the
Panel.action()returns an update, print that update to the terminal.
The loop will end under the following conditions:
The application sends a
thurible.messages.Endmessage,The manager encounters a known exception it cannot recover from.
The manager encounters an unknown exception.
When possible, the manager will send a thurible.messages.Ending
message to announce the end of the loop. If the loop is ending due to
and exception, that exception is passed to the application within
the thurible.messages.Ending message.
Storing Panels¶
To allow your application to pre-load panels and easily switch back
and forth between panels without having to recreate them, the
manager stores all panels sent to it with the
thurible.messages.Store message or created with the
thurible.messages.Alert message. Those messages allow you
to assign a name to the panel, which is then used by other messages,
like thurible.messages.Show, to interact with the stored
panels.
Warning
Managers store panels in a dict object, using the
name given to the panel as the key. This means that if you
provide the same name for two panels, one panel will overwrite
the other panel. For this reason, it is recommended all panels
be given unique names.
Examples¶
The examples directory in the thurible repository provides
examples for how to use managers.
An example of using event_manager() is found in:
examples/eventsplash.py
Examples of using queued_manager() are found in:
examples/favword.py
examples/filereader.py
examples/showsplash.py
examples/tensecs.py