1
0
Fork 0
mirror of synced 2024-05-25 11:31:15 -04:00
dotbot/dotbot/util/module.py
Kurt McKee b5499c7dc5 Separate module importing from plugin identification
This change allows the test framework to reliably specify
which plugins to load and use within the same process.

Previously, plugins were loaded by importing files and then
accessing the Plugin class' list of subclasses.
Now, it's possible to run dotbot multiple times without
plugins accruing across runs with different configurations
and CLI arguments.

In addition, this fixes some circular imports that were
previously avoided because plugins were imported in a function.
2022-05-13 10:44:29 -05:00

46 lines
1.2 KiB
Python

import os
import sys
from dotbot.plugin import Plugin
# We keep references to loaded modules so they don't get garbage collected.
loaded_modules = []
def load(path):
basename = os.path.basename(path)
module_name, extension = os.path.splitext(basename)
loaded_module = load_module(module_name, path)
plugins = []
for name in dir(loaded_module):
possible_plugin = getattr(loaded_module, name)
try:
if issubclass(possible_plugin, Plugin) and possible_plugin is not Plugin:
plugins.append(possible_plugin)
except TypeError:
pass
loaded_modules.append(loaded_module)
return plugins
if sys.version_info >= (3, 5):
import importlib.util
def load_module(module_name, path):
spec = importlib.util.spec_from_file_location(module_name, path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
elif sys.version_info >= (3, 3):
from importlib.machinery import SourceFileLoader
def load_module(module_name, path):
return SourceFileLoader(module_name, path).load_module()
else:
import imp
def load_module(module_name, path):
return imp.load_source(module_name, path)