/usr/share/pyshared/jsb/lib/callbacks.py is in jsonbot 0.84.4-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | # jsb/callbacks.py
#
#
"""
bot callbacks .. callbacks take place on registered events. a precondition
function can optionaly be provided to see if the callback should fire.
"""
## jsb imports
from threads import getname, start_new_thread
from jsb.utils.locking import lockdec
from jsb.utils.exception import handle_exception
from jsb.utils.trace import calledfrom, whichplugin, callstack
from jsb.utils.dol import Dol
## basic imports
import sys
import copy
import thread
import logging
import time
## locks
lock = thread.allocate_lock()
locked = lockdec(lock)
## Callback class
class Callback(object):
""" class representing a callback. """
def __init__(self, modname, func, prereq, kwargs, threaded=False, speed=5):
self.modname = modname
self.plugname = self.modname.split('.')[-1]
self.func = func # the callback function
self.prereq = prereq # pre condition function
self.kwargs = kwargs # kwargs to pass on to function
self.threaded = copy.deepcopy(threaded) # run callback in thread
self.speed = copy.deepcopy(speed) # speed to execute callback with
self.activate = False
self.enable = True
## Callbacks class (holds multiple callbacks)
class Callbacks(object):
"""
dict of lists containing callbacks. Callbacks object take care of
dispatching the callbacks based on incoming events. see Callbacks.check()
"""
def __init__(self):
self.cbs = Dol()
def size(self):
""" return number of callbacks. """
return self.cbs.size()
def add(self, what, func, prereq=None, kwargs=None, threaded=False, nr=False, speed=5):
""" add a callback. """
what = what.upper()
modname = calledfrom(sys._getframe())
if not kwargs: kwargs = {}
if nr != False: self.cbs.insert(nr, what, Callback(modname, func, prereq, kwargs, threaded, speed))
else: self.cbs.add(what, Callback(modname, func, prereq, kwargs, threaded, speed))
logging.debug('added %s (%s)' % (what, modname))
return self
register = add
def unload(self, modname):
""" unload all callbacks registered in a plugin. """
unload = []
for name, cblist in self.cbs.iteritems():
index = 0
for item in cblist:
if item.modname == modname: unload.append((name, index))
index += 1
for callback in unload[::-1]:
self.cbs.delete(callback[0], callback[1])
logging.debug(' unloaded %s (%s)' % (callback[0], modname))
def disable(self, plugname):
""" disable all callbacks registered in a plugin. """
unload = []
for name, cblist in self.cbs.iteritems():
index = 0
for item in cblist:
if item.plugname == plugname: item.activate = False
def activate(self, plugname):
""" activate all callbacks registered in a plugin. """
unload = []
for name, cblist in self.cbs.iteritems():
index = 0
for item in cblist:
if item.plugname == plugname: item.activate = True
def whereis(self, cmnd):
""" show where ircevent.CMND callbacks are registered """
result = []
cmnd = cmnd.upper()
for c, callback in self.cbs.iteritems():
if c == cmnd:
for item in callback:
if not item.plugname in result: result.append(item.plugname)
return result
def list(self):
""" show all callbacks. """
result = []
for cmnd, callbacks in self.cbs.iteritems():
for cb in callbacks:
result.append(getname(cb.func))
return result
def check(self, bot, event):
""" check for callbacks to be fired. """
self.reloadcheck(bot, event)
type = event.cbtype or event.cmnd
if self.cbs.has_key('ALL'):
for cb in self.cbs['ALL']: self.callback(cb, bot, event)
if self.cbs.has_key(type):
target = self.cbs[type]
for cb in target: self.callback(cb, bot, event)
def callback(self, cb, bot, event):
""" do the actual callback with provided bot and event as arguments. """
#if event.stop: logging.info("callbacks - event is stopped.") ; return
event.calledfrom = cb.modname
if not event.bonded: event.bind(bot)
try:
if event.status == "done":
if not event.nolog: logging.debug("callback - event is done .. ignoring")
return
if event.chan and cb.plugname in event.chan.data.denyplug:
logging.debug("%s denied in %s - %s" % (cb.modname, event.channel, event.auth))
return
if cb.prereq:
if not event.nolog: logging.debug('executing in loop %s' % str(cb.prereq))
if not cb.prereq(bot, event): return
if not cb.func: return
if event.isremote(): logging.info('%s - executing REMOTE %s - %s' % (bot.cfg.name, getname(cb.func), event.cbtype))
elif not event.nolog: logging.info('%s - executing %s - %s' % (bot.cfg.name, getname(cb.func), event.cbtype))
event.iscallback = True
if not event.nolog: logging.debug("%s - %s - trail - %s" % (bot.cfg.name, getname(cb.func), callstack(sys._getframe())[::-1]))
#if not event.direct and cb.threaded and not bot.isgae: start_new_thread(cb.func, (bot, event))
time.sleep(0.01)
if cb.threaded and not bot.isgae: start_new_thread(cb.func, (bot, event))
else:
if event.cbtype == "API":
from runner import apirunner
apirunner.put(event.speed or cb.speed, cb.modname, cb.func, bot, event)
elif bot.isgae or event.direct: cb.func(bot, event)
elif not event.dolong:
from runner import callbackrunner
callbackrunner.put(event.speed or cb.speed, cb.modname, cb.func, bot, event)
else:
from runner import longrunner
longrunner.put(event.speed or cb.speed, cb.modname, cb.func, bot, event)
return True
except Exception, ex:
handle_exception()
def reloadcheck(self, bot, event, target=None):
""" check if plugin need to be reloaded for callback, """
from boot import plugblacklist
plugloaded = []
done = []
target = target or event.cbtype or event.cmnd
if not event.nolog: logging.debug("%s - checking for %s events" % (bot.cfg.name, target))
try:
from boot import getcallbacktable
p = getcallbacktable()[target]
except KeyError:
if not event.nolog: logging.debug("can't find plugin to reload for %s" % event.cmnd)
return
if not event.nolog: logging.debug("found %s" % unicode(p))
for name in p:
if name in bot.plugs: done.append(name) ; continue
if plugblacklist and name in plugblacklist.data:
logging.info("%s - %s is in blacklist" % (bot.cfg.name, name))
continue
elif bot.cfg.loadlist and name not in bot.cfg.loadlist:
logging.info("%s - %s is not in loadlist" % (bot.cfg.name, name))
continue
if not event.nolog: logging.debug("%s - on demand reloading of %s" % (bot.cfg.name, name))
try:
mod = bot.plugs.reload(name, force=True, showerror=False)
if mod: plugloaded.append(mod) ; continue
except Exception, ex: handle_exception(event)
if done and not event.nolog: logging.debug("%s - %s is already loaded" % (bot.cfg.name, str(done)))
return plugloaded
## global callbacks
first_callbacks = Callbacks()
callbacks = Callbacks()
last_callbacks = Callbacks()
remote_callbacks = Callbacks()
api_callbacks = Callbacks()
def size():
return "first: %s - callbacks: %s - last: %s - remote: %s" % (first_callbacks.size(), callbacks.size(), last_callbacks.size(), remote_callbacks.size(), api_callbacks.size())
|