]>
Commit | Line | Data |
---|---|---|
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) |