#!/usr/bin/env python3 """ Methods for loading modules. """ import os import sys import importlib def load_module(bot, path): """ Loads a module from the provided path, cleans it up and registers it with the bot's internal callable list. """ module = importlib.import_module(path) if hasattr(module, 'setup'): module.setup(bot) relevant_parts = process_module(module, bot.config) for part in relevant_parts: bot.register_callable(part) def unload_module(bot, name): """ Unloads a module and deletes references to it from the bot's memory. """ old_module = sys.modules[name] # delete references to the module functions from the bot's memory for obj_name, obj in vars(old_module).items(): bot.unregister_callable(obj) del old_module delattr(sys.modules['modules'], name.rpartition('.')[2]) del sys.modules[name] def find_modules(homedir): """ Searches through homedir/modules for python files and returns a dictionary with the module name as the key and the path as the value. """ modules_dir = os.path.join(homedir, "modules") modules = {} for file in os.listdir(modules_dir): if not file.endswith(".py"): continue name = file.replace(".py", "") modules[name] = "modules" + "." + name return modules def process_module(module, config): """ Takes a module object and extracts relevant data objects out of it. Returns all callables(read: functions) and shutdowns(?). """ callables = [] for key, obj in dict.items(vars(module)): if callable(obj): if is_triggerable(obj): process_callable(obj, config) callables.append(obj) return callables def is_triggerable(obj): """ Checks if the given function object is triggerable by Fulvia, eg. has any of a few particular attributes or declarators defined. """ triggerable_attributes = ("commands", "hook", "url_callback", "user_joined") return any(hasattr(obj, attr) for attr in triggerable_attributes) def process_callable(func, config): """ Sets various helper atributes about a given function. """ prefix = config.core.prefix func.thread = getattr(func, "thread", True) func.hook = getattr(func, "hook", False) func.rate = getattr(func, "rate", 0) func.channel_rate = getattr(func, "channel_rate", 0) func.global_rate = getattr(func, "global_rate", 0) func.user_joined = getattr(func, "user_joined", False)