Posts Tagged 'eventmanager'

EventManager en python

Hoy he estado implementando un sistema de plugins para www.sweetter.net, y para ello he decidido utilizar un modelo de señales, de tal forma que se puedan enlazar funciones a señales, y cuando se lance esta señal, se hace una llamada a todas las funciones enlazadas a esta señal.

La idea es simple, pero la implementación lo es aún más. Solo es necesario implementar un par de clases, Event y EventManager.

La clase Event
Como su propio nombre indica, esta clase representa un evento, o señal. Como atributos de clase tiene:

  • (str)self.name, para nombrar a la señal.
  • (dict)self.listeners, para guardar todas las funciones conectadas a esta señal, junto con los posibles parametros de estas.

Como metodos tiene:

  • add(self, function, data=None)
  • , que conecta una funcion a este evento, en data se pueden pasar los parametros de la función, como una tupla, o un dict. Si no se pasan, se llama a la función sin parametros.

  • def delete(self, function), esta es la inversa a la función anterior, desconecta una función de una señal.
  • def called(self, data=None), en esta función es donde está el meollo de la cuestión, ya que se encarga de llamar a las funciones de este evento. Si se pasa el parametro data, pues se utilizan estos parametros para la llamada a todas las funciones conectadas a esta señal

La clase EventManager
Esta clase es la encargada de gestionar todos los eventos que tengamos, y que emite las señales.
Como atributos:

  • (dict)self.events, en este parametro se almacenan todos los eventos.

Como metodos:

  • def add_event(self, Event), este metodo añade un evento al EventManager.
  • def del_event(self, Event), este metodo es el inverso del anterior, borra un evento.
  • def connect(self, event, function, data=None), con este metodo se conecta una función con un evento, el evento debe existir en el event manager.
  • def disconnect(self, event, function), esta es la función inversa a la anterior.
  • def signal(self, event, data=None), esta es la función encargada de mandar señales, así que se llama cuando queramos generar un evento.

Ejemplo de uso

import events
em = events.EventManager()
em.add_event(events.Event('misenal1'))
...
em.add_event(events.Event('otrasenal'))
em.connect('misenal1', print)
em.connect('misenal1', str.join, [['uno', 'dos', 'tres']])
em.connect('otrasenal', str.split, "cadena dos")
...
em.signal('misenal1', 'esto se imprimiria')
em.signal('otrasenal')
...

Aquí el código completo

class Event():
    def __init__(self, name):
        self.name = name
        self.listeners = {}

    def add(self, function, data=None):
        self.listeners[function] = data
    
    def delete(self, function):
        self.listeners.pop(function)

    def called(self, data=None):
        for function, d in self.listeners.items():
            if data is None:
                if d is None:
                    function()
                else:
                    if type(d) == type([]):
                        function(*d)
                    elif type(d) == type({}):
                        function(**d)
                    else:
                        function(d)
            else:
                if type(data) == type([]):
                    function(*data)
                elif type(data) == type({}):
                    function(**data)
                else:
                    function(data)


class EventManager():
    def __init__(self):
        self.events = {}

    def add_event(self, Event):
        self.events[Event.name] = Event

    def del_event(self, Event):
        self.events.pop(Event.name)

    def connect(self, event, function, data=None):
        self.events[event].add(function, data)

    def disconnect(self, event, function):
        self.events[event].delete(function)

    def signal(self, event, data=None):
        if data is None:
            self.events[event].called()
        else:
            self.events[event].called(data)
Anuncios