def reload_module_tree(bot, name, seen=None, silent=False): from types import ModuleType old_module = sys.modules[name] if seen is None: seen = {} if name not in seen: seen[name] = [] for obj in itervalues(vars(old_module)): if callable(obj): if (getattr(obj, '__name__', None) == 'shutdown' and obj in bot.shutdown_methods): # If this is a shutdown method, call it first. try: stderr( "calling %s.%s" % ( obj.__module__, obj.__name__, ) ) obj(bot) except Exception as e: stderr( "Error calling shutdown method for module %s:%s" % ( obj.__module__, e ) ) bot.unregister(obj) elif (type(obj) is ModuleType and obj.__name__.startswith(name + '.') and obj.__name__ not in sys.builtin_module_names): # recurse into submodules, see issue 1056 if obj not in seen[name]: seen[name].append(obj) reload(obj) reload_module_tree(bot, obj.__name__, seen, silent) modules = sopel.loader.enumerate_modules(bot.config) if name not in modules: return # Only reload the top-level module, once recursion is finished # Also delete the setup function # Sub-modules shouldn't have setup functions, so do after the recursion check if hasattr(old_module, "setup"): delattr(old_module, "setup") path, type_ = modules[name] load_module(bot, name, path, type_, silent)
def clean_module(module, config): callables = [] shutdowns = [] jobs = [] for obj in itervalues(vars(module)): if isinstance(obj, collections.Callable): if getattr(obj, '__name__', None) == 'shutdown': shutdowns.append(obj) elif is_triggerable(obj): clean_callable(obj, config) callables.append(obj) elif hasattr(obj, 'interval'): clean_callable(obj, config) jobs.append(obj) return callables, jobs, shutdowns
def clean_module(module, config): callables = [] shutdowns = [] jobs = [] for obj in itervalues(vars(module)): if callable(obj): if getattr(obj, "__name__", None) == "shutdown": shutdowns.append(obj) elif is_triggerable(obj): clean_callable(obj, config) callables.append(obj) elif hasattr(obj, "interval"): clean_callable(obj, config) jobs.append(obj) return callables, jobs, shutdowns
def clean_module(module, config): """Clean a module and return its command, rule, job, etc. callables. :param module: the module to clean :type module: :term:`module` :param config: Sopel's settings :type config: :class:`sopel.config.Config` :return: a tuple with triggerable, job, shutdown, and url functions :rtype: tuple This function will parse the ``module`` looking for callables: * shutdown actions * triggerables (commands, rules, etc.) * jobs * URL callbacks This function will set all the default attributes expected for a Sopel callable, i.e. properties related to threading, docs, examples, rate limiting, commands, rules, and other features. """ callables = [] shutdowns = [] jobs = [] urls = [] for obj in itervalues(vars(module)): if callable(obj): is_sopel_callable = getattr(obj, '_sopel_callable', False) is True if getattr(obj, '__name__', None) == 'shutdown': shutdowns.append(obj) elif not is_sopel_callable: continue elif is_triggerable(obj): clean_callable(obj, config) callables.append(obj) elif hasattr(obj, 'interval'): clean_callable(obj, config) jobs.append(obj) elif is_url_callback(obj): clean_callable(obj, config) urls.append(obj) return callables, jobs, shutdowns, urls
def clean_module(module, config): callables = [] shutdowns = [] jobs = [] urls = [] for obj in itervalues(vars(module)): if callable(obj): is_sopel_callable = getattr(obj, '_sopel_callable', False) is True if getattr(obj, '__name__', None) == 'shutdown': shutdowns.append(obj) elif not is_sopel_callable: continue elif is_triggerable(obj): clean_callable(obj, config) callables.append(obj) elif hasattr(obj, 'interval'): clean_callable(obj, config) jobs.append(obj) elif is_url_callback(obj): clean_callable(obj, config) urls.append(obj) return callables, jobs, shutdowns, urls