fulvia/loader.py

106 lines
2.8 KiB
Python
Raw Normal View History

2018-03-16 03:13:43 -04:00
#!/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)
bot.register_callable(relevant_parts)
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
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")
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
doc = func.__doc__
if doc:
doc = doc.strip()
doc = doc.replace("\t", "")
doc = doc.replace("\n\n", "\x00")
doc = doc.replace("\n", " ")
doc = doc.replace("\x00", "\n")
func._docs = {}
func.example = getattr(func, "example", [(None, None)])
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)
if hasattr(func, 'commands'):
if hasattr(func, 'example'):
for n, example in enumerate(func.example):
ex_input = example[0]
if not ex_input:
continue
if ex_input[0] != prefix:
ex_input = prefix + ex_input
func.example[n] = (ex_input, example[1])
if doc:
for command in func.commands:
func._docs[command] = (doc, func.example)