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