diff --git a/bot.py b/bot.py index cd1e6e3..413849c 100644 --- a/bot.py +++ b/bot.py @@ -1,29 +1,11 @@ import teambot, sys, traceback, plugin, os -import importlib, importlib.util +import impmod BOTOP = "~minerobber@127.0.0.1" PREFIX = "!" PLUGIN_MODULES = dict() PLUGIN_SPECS = dict() -# hacky re-implementation of reload, uses importlib internals and hardcoded stuffs -def reloadModule(modname): - if modname not in PLUGIN_MODULES: - return False - if modname not in sys.modules: - sys.modules[modname]=PLUGIN_MODULES[modname] - # Alright, this needs some explaining. - # When you do importlib.reload, it does some juju magic shist to find the spec and calls importlib._bootstrap._exec. - # When you dynamically import a module it won't do its magic correctly and it'll error. - # Luckily, we can skip all the juju magic since we can just store the spec. - try: - importlib._bootstrap._exec(PLUGIN_SPECS[modname],PLUGIN_MODULES[modname]) - except: - print("On reloading `{}`:".format(modname)) - traceback.print_exc() - return False - return True - class MinerbotPhoenix(teambot.Handler): def on_connection_established(self,*args): self.load_modules() @@ -35,19 +17,11 @@ class MinerbotPhoenix(teambot.Handler): def load_module(self,modname,path): if modname in PLUGIN_MODULES: print("{} already imported, reloading".format(modname)) - if reloadModule(modname): - print("{} reloaded".format(modname)) - else: - print("{} reload errored, skipping".format(modname)) + PLUGIN_MODULES[modname].reload() return try: print("importing {}".format(modname)) - spec = importlib.util.spec_from_file_location(modname,path) - PLUGIN_SPECS[modname]=spec - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) - PLUGIN_MODULES[modname]=module - sys.modules[modname]=module + PLUGIN_MODULES[modname]=impmod.Module(modname,path) except: print("Unable to load plugin {}".format(modname)) traceback.print_exc() diff --git a/impmod.py b/impmod.py new file mode 100644 index 0000000..db430cb --- /dev/null +++ b/impmod.py @@ -0,0 +1,19 @@ +import importlib, importlib.util, sys + +class Module: + """A module. Stores module object, spec object, and handles reloading.""" + def __init__(self,modname,path=None): + if path is None: + path = modname+".py" + self.modname, self.path = modname, path + self.spec = importlib.util.spec_from_file_location(modname,path) + self.module = importlib.util.module_from_spec(self.spec) + self.spec.loader.exec_module(self.module) + def reload(self): + if self.modname not in sys.modules: + sys.modules[self.modname]=self.module + # Alright, this needs some explaining. + # When you do importlib.reload, it does some juju magic shist to find the spec and calls importlib._bootstrap._exec. + # When you dynamically import a module it won't do its magic correctly and it'll error. + # Luckily, we can skip all the juju magic since we can just store the spec. + importlib._bootstrap._exec(self.spec,self.module)