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