]> jfr.im git - erebus.git/blame - ctlmod.py
bot - update error handling
[erebus.git] / ctlmod.py
CommitLineData
931c88a4 1# Erebus IRC bot - Author: John Runyon
2# module loading/unloading/tracking code
3
b9c6eb1d 4import sys, time
e4255e70 5import modlib
db50981b 6
7modules = {}
e4255e70 8dependents = {}
db50981b 9
10def isloaded(modname): return modname in modules
d431e543 11def modhas(modname, attname): return getattr(modules[modname], attname, None) is not None
db50981b 12
b9c6eb1d 13def load(parent, modname, dependent=False):
14 #wrapper to call _load and print return
15 if dependent:
16 print "Loading dependency %s..." % (modname),
17 else:
3d724d3a 18 print "%09.3f [MOD] [#] Loading %s... " % (time.time() % 100000, modname),
b9c6eb1d 19 modstatus = _load(parent, modname, dependent)
20 if not modstatus:
21 print str(modstatus)
22 elif modstatus == True:
23 if dependent:
24 print "OK. ",
25 else:
26 print "OK."
27 else:
28 print modstatus
29 return modstatus
30
31def _load(parent, modname, dependent=False):
db50981b 32 if not isloaded(modname):
6e2b575f 33 sys.path.insert(0, 'modules')
96d0b31e 34 try:
35 mod = __import__(modname)
8ba56606 36 reload(mod) #in case it's been previously loaded.
96d0b31e 37 except BaseException as e: #we don't want even sys.exit() to crash us (in case of malicious module) so use BaseException
38 return modlib.error(e)
6e2b575f 39 finally:
40 del sys.path[0] #remove ./modules from path, in case there's a name conflict
20df9fbb 41
e4255e70 42
6b2c681d 43 if not hasattr(mod, 'modinfo'):
44 return modlib.error('no modinfo')
45
a76c4bd8 46 if parent.APIVERSION not in mod.modinfo['compatible']:
e4255e70 47 return modlib.error('API-incompatible')
48
db50981b 49 modules[modname] = mod
e4255e70 50 dependents[modname] = []
51
52 for dep in mod.modinfo['depends']:
53 if dep not in modules:
b9c6eb1d 54 depret = load(parent, dep, dependent=True)
e4255e70 55 if not depret:
56 return
57 dependents[dep].append(modname)
58
59
db50981b 60 ret = mod.modstart(parent)
e4255e70 61 if ret is not None and not ret:
db50981b 62 del modules[modname]
e4255e70 63 del dependents[modname]
64 for dep in mod.modinfo['depends']:
65 dependents[dep].remove(modname)
db50981b 66 return ret
e4255e70 67 else: #if not isloaded...else:
68 return modlib.error('already loaded')
db50981b 69
70def unload(parent, modname):
71 if isloaded(modname):
e4255e70 72 for dependent in dependents[modname]:
73 unload(parent, dependent)
74 for dep in dependents[modname]:
75 dependents[dep].remove(modname)
5a81c82b 76 ret = modules[modname].modstop(parent)
77 del modules[modname]
78 return ret
db50981b 79 else:
e4255e70 80 return modlib.error('already unloaded')
db50981b 81
82def reloadmod(parent, modname):
83 if isloaded(modname):
d431e543 84 if modhas(modname, 'modrestart'): modules[modname].modrestart(parent)
85 else: modules[modname].modstop(parent)
db50981b 86
e3878612 87 try:
65b86c90 88 reload(modules[modname])
96d0b31e 89 except BaseException as e:
e3878612 90 return modlib.error(e)
db50981b 91
8ba56606 92 if modhas(modname, 'modrestarted'): ret = modules[modname].modrestarted(parent)
93 else: ret = modules[modname].modstart(parent)
db50981b 94
8ba56606 95 return ret
db50981b 96 else:
e3878612 97 return load(parent, modname)
98
db50981b 99
100def loadall(parent, modlist):
101 for m in modlist: load(parent, m)
102def unloadall(parent, modlist):
103 for m in modlist: unload(parent, m)
104def reloadall(parent, modlist):
105 for m in modlist: reloadmod(parent, m)
106
107sys.path.append('modules')