Added functionality to load, unload and reload modules from a command!
This commit is contained in:
parent
41817ce255
commit
29609fffd7
3 changed files with 80 additions and 23 deletions
|
@ -179,7 +179,7 @@ class EventHook(object):
|
|||
returns.append(hook.call(event))
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
self.bot.log.error("failed to call event \"%s", [
|
||||
self.bot.log.error("failed to call event \"%s\"", [
|
||||
event_path], exc_info=True)
|
||||
called += 1
|
||||
|
||||
|
@ -202,11 +202,9 @@ class EventHook(object):
|
|||
child_name_lower = child_name.lower()
|
||||
if child_name_lower in self._children:
|
||||
del self._children[child_name_lower]
|
||||
def get_children(self):
|
||||
return self._children.keys()
|
||||
|
||||
def check_purge(self):
|
||||
if len(self.get_hooks()) == 0 and len(self._children
|
||||
if len(self.get_hooks()) == 0 and len(self.get_children()
|
||||
) == 0 and not self.parent == None:
|
||||
self.parent.remove_child(self.name)
|
||||
self.parent.check_purge()
|
||||
|
@ -218,9 +216,16 @@ class EventHook(object):
|
|||
def purge_context(self, context):
|
||||
if self.has_context(context):
|
||||
self.remove_context(context)
|
||||
for child in self.get_children():
|
||||
for child_name in self.get_children()[:]:
|
||||
child = self.get_child(child_name)
|
||||
child.purge_context(context)
|
||||
if child.is_empty():
|
||||
self.remove_child(child_name)
|
||||
|
||||
def get_hooks(self):
|
||||
return sorted(self._hooks + list(itertools.chain.from_iterable(
|
||||
self._context_hooks.values())), key=lambda e: e.priority)
|
||||
def get_children(self):
|
||||
return list(self._children.keys())
|
||||
def is_empty(self):
|
||||
return len(self.get_hooks() + self.get_children()) == 0
|
||||
|
|
|
@ -10,13 +10,15 @@ class ModuleManager(object):
|
|||
def list_modules(self):
|
||||
return sorted(glob.glob(os.path.join(self.directory, "*.py")))
|
||||
|
||||
def module_name(self, filename):
|
||||
return os.path.basename(filename).rsplit(".py", 1)[0].lower()
|
||||
def _module_name(self, path):
|
||||
return os.path.basename(path).rsplit(".py", 1)[0].lower()
|
||||
def _module_path(self, name):
|
||||
return os.path.join(self.directory, "%s.py" % name)
|
||||
|
||||
def _load_module(self, filename):
|
||||
name = self.module_name(filename)
|
||||
def _load_module(self, name):
|
||||
path = self._module_path(name)
|
||||
|
||||
with open(filename) as module_file:
|
||||
with open(path) as module_file:
|
||||
while True:
|
||||
line = module_file.readline().strip()
|
||||
line_split = line.split(" ")
|
||||
|
@ -36,11 +38,11 @@ class ModuleManager(object):
|
|||
if not "bitbot_%s" % line_split[1].lower() in sys.modules:
|
||||
if not line_split[1].lower() in self.waiting_requirement:
|
||||
self.waiting_requirement[line_split[1].lower()] = set([])
|
||||
self.waiting_requirement[line_split[1].lower()].add(filename)
|
||||
self.waiting_requirement[line_split[1].lower()].add(path)
|
||||
return None
|
||||
else:
|
||||
break
|
||||
module = imp.load_source(name, filename)
|
||||
module = imp.load_source(name, path)
|
||||
|
||||
if not hasattr(module, "Module"):
|
||||
raise ImportError("module '%s' doesn't have a Module class.")
|
||||
|
@ -60,23 +62,34 @@ class ModuleManager(object):
|
|||
"module name '%s' attempted to be used twice.")
|
||||
return module_object
|
||||
|
||||
def load_module(self, filename):
|
||||
name = self.module_name(filename)
|
||||
def load_module(self, name):
|
||||
try:
|
||||
module = self._load_module(filename)
|
||||
module = self._load_module(name)
|
||||
except ImportError as e:
|
||||
sys.stderr.write("module '%s' not loaded: Could not resolve import.\n" % filename)
|
||||
self.bot.log.error("failed to load module \"%s\": %s",
|
||||
[name, e.msg])
|
||||
return
|
||||
if module:
|
||||
self.modules[module._import_name] = module
|
||||
if name in self.waiting_requirement:
|
||||
for filename in self.waiting_requirement:
|
||||
self.load_module(filename)
|
||||
sys.stderr.write("module '%s' loaded.\n" % filename)
|
||||
for requirement_name in self.waiting_requirement:
|
||||
self.load_module(requirement_name)
|
||||
self.bot.log.info("Module '%s' loaded", [name])
|
||||
else:
|
||||
sys.stderr.write("module '%s' not loaded.\n" % filename)
|
||||
self.bot.log.error("Module '%s' not loaded", [name])
|
||||
|
||||
def load_modules(self, whitelist=None):
|
||||
for filename in self.list_modules():
|
||||
if whitelist == None or filename in whitelist:
|
||||
self.load_module(filename)
|
||||
for path in self.list_modules():
|
||||
name = self._module_name(path)
|
||||
if whitelist == None or name in whitelist:
|
||||
self.load_module(name)
|
||||
|
||||
def unload_module(self, name):
|
||||
module = self.modules[name]
|
||||
del self.modules[name]
|
||||
|
||||
event_context = module._event_context
|
||||
self.events.purge_context(event_context)
|
||||
|
||||
del sys.modules[name]
|
||||
del module
|
||||
|
|
39
modules/modules.py
Normal file
39
modules/modules.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
|
||||
class Module(object):
|
||||
def __init__(self, bot, events):
|
||||
self.bot = bot
|
||||
events.on("received.command.loadmodule").hook(self.load,
|
||||
min_args=1, permission="load-module", help="Load a module",
|
||||
usage="<module-name>")
|
||||
events.on("received.command.unloadmodule").hook(self.unload,
|
||||
min_args=1, permission="unload-module", help="Unload a module",
|
||||
usage="<module-name>")
|
||||
events.on("received.command.reloadmodule").hook(self.reload,
|
||||
min_args=1, permission="reload-module", help="Reload a module",
|
||||
usage="<module-name>")
|
||||
|
||||
def load(self, event):
|
||||
name = event["args_split"][0].lower()
|
||||
if name in self.bot.modules.modules:
|
||||
event["stderr"].write("Module '%s' is already loaded" % name)
|
||||
return
|
||||
self.bot.modules.load_module(name)
|
||||
event["stdout"].write("Loaded '%s'" % name)
|
||||
|
||||
def unload(self, event):
|
||||
name = event["args_split"][0].lower()
|
||||
if not name in self.bot.modules.modules:
|
||||
event["stderr"].write("Module '%s' isn't loaded" % name)
|
||||
return
|
||||
self.bot.modules.unload_module(name)
|
||||
event["stdout"].write("Unloaded '%s'" % name)
|
||||
|
||||
def reload(self, event):
|
||||
name = event["args_split"][0].lower()
|
||||
if not name in self.bot.modules.modules:
|
||||
event["stderr"].write("Module '%s' isn't loaded" % name)
|
||||
return
|
||||
self.bot.modules.unload_module(name)
|
||||
self.bot.modules.load_module(name)
|
||||
event["stdout"].write("Reloaded '%s'" % name)
|
Loading…
Reference in a new issue