From 060bad105dc2569fc485adb03b985aa2ab5d367e Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Tue, 22 Feb 2022 23:47:09 +0000 Subject: Move new utilities to the util namespace --- botcore/utils/extensions.py | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 botcore/utils/extensions.py (limited to 'botcore/utils/extensions.py') diff --git a/botcore/utils/extensions.py b/botcore/utils/extensions.py new file mode 100644 index 00000000..c8f200ad --- /dev/null +++ b/botcore/utils/extensions.py @@ -0,0 +1,52 @@ +"""Utilities for loading discord extensions.""" + +import importlib +import inspect +import pkgutil +import types +from typing import NoReturn + + +def unqualify(name: str) -> str: + """ + Return an unqualified name given a qualified module/package `name`. + + Args: + name: The module name to unqualify. + + Returns: + The unqualified module name. + """ + return name.rsplit(".", maxsplit=1)[-1] + + +def walk_extensions(module: types.ModuleType) -> frozenset[str]: + """ + Yield extension names from the bot.exts subpackage. + + Args: + module (types.ModuleType): The module to look for extensions in. + + Returns: + A set of strings that can be passed directly to :obj:`discord.ext.commands.Bot.load_extension`. + """ + + def on_error(name: str) -> NoReturn: + raise ImportError(name=name) # pragma: no cover + + modules = set() + + for module_info in pkgutil.walk_packages(module.__path__, f"{module.__name__}.", onerror=on_error): + if unqualify(module_info.name).startswith("_"): + # Ignore module/package names starting with an underscore. + continue + + if module_info.ispkg: + imported = importlib.import_module(module_info.name) + if not inspect.isfunction(getattr(imported, "setup", None)): + # If it lacks a setup function, it's not an extension. + continue + + modules.add(module_info.name) + + return frozenset(modules) -- cgit v1.2.3