triggerset: Support for managing triggers and handlers

This module defines one class, TriggerSet, which implements a simple callback mechanism. A TriggerSet instance contains a set of named triggers, each of which may have a number of handlers registered with it. Activating a trigger in the instance causes all its handlers to be called, in the order of registration.

Example

The following example creates a TriggerSet instance named ts and adds a trigger named conrad. Two handlers are registered: the first reports its arguments; the second reports its arguments and then deregisters itself.

import triggerset

ts = triggerset.TriggerSet()
ts.add_trigger('conrad')

def first(trigger, trigger_data):
    print('trigger =', trigger)
    print('  trigger_data =', trigger_data)

class Second:

    def __init__(self, ts):
        self.triggerset = ts
        self.handler = None

    def trigger_handler(self, trigger, trigger_data):
        print('trigger =', trigger)
        print('  triggerset =', self.triggerset)
        print('  handler =', self.handler)
        print('  trigger_data =', trigger_data)
        if self.triggerset and self.handler:
            self.triggerset.remove_handler(self.handler)
            self.handler = None

h1 = ts.add_handler('conrad', first)
o = Second(ts)
o.handler = ts.add_handler('conrad', o.trigger_handler)

ts.activate_trigger('conrad', 1)
print()
ts.activate_trigger('conrad', 2)

The output from this example is:

trigger = conrad
  trigger_data = 1
trigger = conrad
  triggerset = <triggerset.TriggerSet instance at 1400f3010>
  handler = <triggerset._TriggerHandler instance at 140097ac0>
  trigger_data = 1

trigger = conrad trigger_data = 2

If a handler returns the value triggerset.DEREGISTER, then the handler will be deregistered after it returns. Therfore, the ‘Second.handler()’ method above could have been written more simply as:

def trigger_handler(trigger, trigger_data):
    print('trigger =', trigger,
        'triggerset =', self.triggerset,
        'handler =', self.handler,
        'trigger_data =', trigger_data)
    self.handler = None
    return triggerset.DEREGISTER
class TriggerSet

Bases: object

Keep track of related groups of triggers.

activate_trigger(name, data, absent_okay=False)

Invoke all handlers registered with the given name.

triggerset.activate_trigger(name, data) => None

If no trigger corresponds to name, an exception is raised. Handlers are invoked in the order in which they were registered, and are called in the following manner:

func(name, data)

where func is the function previously registered with add_handler, name is the name of the trigger, and data is the data argument to the activate_trigger() call.

During trigger activation, handlers may add new handlers or delete existing handlers. These operations, however, are deferred until after all handlers have been invoked; in particular, for the current trigger activation, newly added handlers will not be invoked and newly deleted handlers will be invoked.

add_dependency(trigger, after)

Specify firing order dependency for ‘trigger’.

triggerset.add_dependency(trigger, after) => None

Specifies that ‘trigger’ should be fired after all triggers in the ‘after’ list when a trigger set is blocked and released. If the dependency relationship conflicts with a previously specified dependency, a ‘ValueError’ exception is thrown. If any name given is not a trigger name, a ‘KeyError’ exception is thrown.

Note that the dependency information is _only_ used when an entire trigger set is blocked and released, and not used for blocking and releasing of individual triggers.

add_handler(name, func)

Register a function with the trigger with the given name.

triggerset.add_handler(name, func) => handler

If no trigger corresponds to name, an exception is raised. add_handler returns a handler for use with remove_handler.

add_trigger(name, *, usage_cb=None, after=None, default_one_time=False, remove_bad_handlers=False)

Add a trigger with the given name.

triggerset.add_trigger(name) => None

The name should be a string. If a trigger by the same name already exists, an exception is raised.

The optional ‘usage_cb’ argument can be used to provide a callback function for when the trigger goes from no handlers registered to at least one registered, and vice versa. The callback function will be given the trigger name and 1 or 0 (respectively) as arguments.

The optional argument ‘default_one_time’ (default False) may be used to designate triggers whose registered handlers should only be called once. For example, an “exit trigger” may only want its handler run once and then discarded without having the handler explicitly deregister itself or return DEREGISTER.

The optional argument ‘after’ (default None) may be a list of trigger names, and is passed to a call to ‘add_dependency’ after the new trigger has been created.

if ‘remove_bad_handlers’ is True, then handlers that throw errors will be removed from the list of handlers if they throw an error.

block()

Block all triggers from firing until released.

triggerset.block() => None

block_trigger(name)

Block all handlers registered with the given name.

triggerset.block_trigger(name) => None

If no trigger corresponds to name, an exception is raised. block_trigger()/release_trigger() may be nested inside other block_trigger()/release_trigger() pairs.

delete_trigger(name)

Remove a trigger with the given name.

triggerset.delete_trigger(name) => None

The name should be a string. If no trigger corresponds to the name, an exception is raised.

has_handlers(name)

Return if the trigger with the given name has any handlers.

triggerset.has_handlers(name) => bool

If no trigger corresponds to name, an exception is raised.

has_trigger(name)

Check if trigger exists.

is_trigger_blocked(name)

Is named trigger blocked?

release()

Release trigger blocks and fire trigger in dependency order.

triggerset.release() => boolean

Return ‘True’ if triggers were blocked, ‘False’ otherwise.

Dependency order is defined by either the ‘add_dependency’ method or providing list specified in the ‘after’ keyword to ‘add_trigger’.

release_trigger(name)

Release all handlers registered with the given name.

triggerset.release_trigger(name) => None

If no trigger corresponds to name, an exception is raised. The last call to activate_trigger() made between the outermost block_trigger()/release_trigger() pair is executed.

remove_handler(handler)

Deregister a handler.

triggerset.remove_handler(handler) => None

The handler should be the return value from a previous call to add_handler. If the given handler is invalid, an exception is raised.

trigger_handlers(name)

Return functions registered for trigger with the given name.

triggerset.trigger_handlers(name) => list

If no trigger corresponds to name, an exception is raised.

trigger_names()

Return an unordered list of the trigger names (dict keys).

triggerset.trigger_names() => list