b5499c7dc5
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.
46 lines
1.2 KiB
Python
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)
|