# -*- coding: utf-8 -*- from traceback import print_exc from time import time class EventManager: """ Handles all Event related task, also stores an Event queue for clients, so they can retrieve them later. **Known Events:** Most hook methods exists as events. These are some additional known events. ===================== ================ =========================================================== Name Arguments Description ===================== ================ =========================================================== metaEvent eventName, *args Called for every event, with eventName and orginal args downloadPreparing fid A download was just queued and will be prepared now. downloadStarts fid A plugin will immediately starts the download afterwards. linksAdded links, pid Someone just added links, you are able to modify the links. allDownloadsProcessed Every link was handled, pyload would idle afterwards. allDownloadsFinished Every download in queue is finished. unrarFinished folder, fname An Unrar job finished configChanged sec, opt, value The config was changed. ===================== ================ =========================================================== | Notes: | allDownloadsProcessed is *always* called before allDownloadsFinished. | configChanged is *always* called before pluginConfigChanged. """ CLIENT_EVENTS = ("packageUpdated", "packageInserted", "linkUpdated", "packageDeleted") def __init__(self, core): self.core = core self.log = core.log # uuid : list of events self.clients = {} self.events = {"metaEvent": []} def getEvents(self, uuid): """ Get accumulated events for uuid since last call, this also registeres new client """ if uuid not in self.clients: self.clients[uuid] = Client() return self.clients[uuid].get() def addEvent(self, event, func): """Adds an event listener for event name""" if event in self.events: if func in self.events[event]: self.log.debug("Function already registered %s" % func) else: self.events[event].append(func) else: self.events[event] = [func] def removeEvent(self, event, func): """removes previously added event listener""" if event in self.events: self.events[event].remove(func) def dispatchEvent(self, event, *args): """dispatches event with args""" for f in self.events["metaEvent"]: try: f(event, *args) except Exception, e: self.log.warning("Error calling event handler %s: %s, %s, %s" % ("metaEvent", f, args, str(e))) if self.core.debug: print_exc() if event in self.events: for f in self.events[event]: try: f(*args) except Exception, e: self.log.warning("Error calling event handler %s: %s, %s, %s" % (event, f, args, str(e))) if self.core.debug: print_exc() # append to client event queue if event in self.CLIENT_EVENTS: for uuid, client in self.clients.items(): if client.delete(): del self.clients[uuid] else: client.append(event, args) def removeFromEvents(self, func): """ Removes func from all known events """ for name, events in self.events.iteritems(): if func in events: events.remove(func) class Client: # delete clients after this time TIMEOUT = 60 * 60 # max events, if this value is reached you should assume that older events were dropped MAX = 30 def __init__(self): self.lastActive = time() self.events = [] def delete(self): return self.lastActive + self.TIMEOUT < time() def append(self, event, args): ev = (event, args) if ev not in self.events: self.events.insert(0, ev) del self.events[self.MAX:] def get(self): self.lastActive = time() events = self.events self.events = [] return [(ev, [str(x) for x in args]) for ev, args in events]