X-Git-Url: https://jfr.im/git/erebus.git/blobdiff_plain/a28e2ae95b1012933a01f3fa992d9f6954f82346..52c80cff91dce5fa14ae903c6c2bf20533ccca46:/ctlmod.py diff --git a/ctlmod.py b/ctlmod.py index 4d12d21..3e30892 100644 --- a/ctlmod.py +++ b/ctlmod.py @@ -1,13 +1,16 @@ # Erebus IRC bot - Author: John Runyon +# vim: fileencoding=utf-8 # module loading/unloading/tracking code from __future__ import print_function -import sys, time +import sys, time, importlib, traceback import modlib if sys.version_info.major >= 3: - from importlib import reload + from importlib import reload # reload is only available as a global in Py2, only in importlib in Py3 +else: + importlib.invalidate_caches = lambda: None # invalidate_caches doesn't exist in Py2 modules = {} dependents = {} @@ -17,7 +20,7 @@ def isloaded(modname): return modname in modules def modhas(modname, attname): return getattr(modules[modname], attname, None) is not None def load(parent, modname, dependent=False): - #wrapper to call _load and print return + """Wrapper to call _load and print the return value.""" if dependent: print("(Loading dependency %s..." % (modname), end=' ') else: @@ -28,6 +31,8 @@ def load(parent, modname, dependent=False): print("failed: %s)" % (modstatus), end=' ') else: print("failed: %s." % (modstatus)) + if isinstance(modstatus, modlib.error) and isinstance(modstatus.errormsg, BaseException): + traceback.print_exception(modstatus.errormsg) elif modstatus == True: if dependent: print("OK)", end=' ') @@ -41,11 +46,12 @@ def load(parent, modname, dependent=False): return modstatus def _load(parent, modname, dependent=False): + """Load and return the new status of the module.""" successstatus = [] if not isloaded(modname): + importlib.invalidate_caches() try: - mod = __import__('modules.'+modname, globals(), locals(), ['*'], 0) - # ^ fromlist doesn't actually do anything(?) but it means we don't have to worry about this returning the top-level "modules" object + mod = importlib.import_module('modules.'+modname) reload(mod) #in case it's been previously loaded. except Exception as e: return modlib.error(e) @@ -74,15 +80,17 @@ def _load(parent, modname, dependent=False): if bool(int(parent.cfg.get('autoloads', dep, default=1))): if dep not in modules: depret = load(parent, dep, dependent=True) - if depret is not None: - if not depret: - successstatus.append("softdep %s failed" % (dep)) + if depret is not None and not depret: + successstatus.append("softdep %s failed" % (dep)) else: successstatus.append("softdep %s disabled" % (dep)) #swallow errors loading - softdeps are preferred, not required - ret = mod.modstart(parent) + try: + ret = mod.modstart(parent) + except Exception as e: + return modlib.error(e) if ret is None: ret = True if not ret: