aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar jesopo2018-09-01 11:29:26 +0100
committerGravatar jesopo2018-09-01 11:29:26 +0100
commit29609fffd77e495e86e6ba1a1f7f9e25d1607e1e (patch)
treec6805f1d164d099d4085b2a1ac73c03377c13bd0
parentAdd Utils.bold and Utils.underline (diff)
signature
Added functionality to load, unload and reload modules from a command!
-rw-r--r--EventManager.py15
-rw-r--r--ModuleManager.py49
-rw-r--r--modules/modules.py39
3 files changed, 80 insertions, 23 deletions
diff --git a/EventManager.py b/EventManager.py
index 4ca5837c..326192ad 100644
--- a/EventManager.py
+++ b/EventManager.py
@@ -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
diff --git a/ModuleManager.py b/ModuleManager.py
index 812edb71..404502e8 100644
--- a/ModuleManager.py
+++ b/ModuleManager.py
@@ -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
diff --git a/modules/modules.py b/modules/modules.py
new file mode 100644
index 00000000..0138be1b
--- /dev/null
+++ b/modules/modules.py
@@ -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)