]> jfr.im git - erebus.git/blob - ctlmod.py
update module loading system
[erebus.git] / ctlmod.py
1 # Erebus IRC bot - Author: John Runyon
2 # module loading/unloading/tracking code
3
4 import sys, time
5 import modlib
6
7 modules = {}
8 dependents = {}
9
10 def isloaded(modname): return modname in modules
11 def modhas(modname, attname): return getattr(modules[modname], attname, None) is not None
12
13 def load(parent, modname, dependent=False):
14 #wrapper to call _load and print return
15 if dependent:
16 print "Loading dependency %s..." % (modname),
17 else:
18 print "%09.3f [MOD] [#] Loading %s... " % (time.time() % 100000, modname),
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
31 def _load(parent, modname, dependent=False):
32 if not isloaded(modname):
33 try:
34 mod = __import__('modules.'+modname, globals(), locals(), ['*'], -1)
35 # ^ fromlist doesn't actually do anything(?) but it means we don't have to worry about this returning the top-level "modules" object
36 reload(mod) #in case it's been previously loaded.
37 except Exception as e:
38 return modlib.error(e)
39
40
41 if not hasattr(mod, 'modinfo'):
42 return modlib.error('no modinfo')
43
44 if parent.APIVERSION not in mod.modinfo['compatible']:
45 return modlib.error('API-incompatible')
46
47 modules[modname] = mod
48 dependents[modname] = []
49
50 for dep in mod.modinfo['depends']:
51 if dep not in modules:
52 depret = load(parent, dep, dependent=True)
53 if not depret:
54 return
55 dependents[dep].append(modname)
56
57
58 ret = mod.modstart(parent)
59 if ret is not None and not ret:
60 del modules[modname]
61 del dependents[modname]
62 for dep in mod.modinfo['depends']:
63 dependents[dep].remove(modname)
64 return ret
65 else: #if not isloaded...else:
66 return modlib.error('already loaded')
67
68 def unload(parent, modname):
69 if isloaded(modname):
70 for dependent in dependents[modname]:
71 unload(parent, dependent)
72 for dep in dependents[modname]:
73 dependents[dep].remove(modname)
74 ret = modules[modname].modstop(parent)
75 del modules[modname]
76 return ret
77 else:
78 return modlib.error('already unloaded')
79
80 def reloadmod(parent, modname):
81 if isloaded(modname):
82 if modhas(modname, 'modrestart'): modules[modname].modrestart(parent)
83 else: modules[modname].modstop(parent)
84
85 try:
86 reload(modules[modname])
87 except BaseException as e:
88 return modlib.error(e)
89
90 if modhas(modname, 'modrestarted'): ret = modules[modname].modrestarted(parent)
91 else: ret = modules[modname].modstart(parent)
92
93 return ret
94 else:
95 return load(parent, modname)
96
97
98 def loadall(parent, modlist):
99 for m in modlist: load(parent, m)
100 def unloadall(parent, modlist):
101 for m in modlist: unload(parent, m)
102 def reloadall(parent, modlist):
103 for m in modlist: reloadmod(parent, m)