Make set of plugins available in context
This is useful for plugins like dotbot-if [1] that want to instantiate their own Dispatcher. Previously, the Dispatcher found the set of available plugins on its own, but as ofb5499c7dc5
, this was changed so that plugins are passed in. Given that it has been over two years since this behavior has been broken/changed, reverting to the previous behavior of having the Dispatcher auto-load plugins might not be ideal, which is why this patch instead makes the set of plugins available via the Context for plugins to use. This was reported in the Dotbot repository [2], and earlier in dotbot-if [3]. dotbot-if is currently using a workaround [4] that was originally implemented in dotbot-ifplatform [5]. [1]: https://github.com/wonderbeyond/dotbot-if [2]: https://github.com/anishathalye/dotbot/issues/339 [3]: https://github.com/wonderbeyond/dotbot-if/issues/1 [4]: https://github.com/wonderbeyond/dotbot-if/pull/2 [5]:e35b5c0d71
This commit is contained in:
parent
4edfa82607
commit
8c2dc8cbc6
4 changed files with 41 additions and 5 deletions
|
@ -8,11 +8,11 @@ class Context:
|
||||||
Contextual data and information for plugins.
|
Contextual data and information for plugins.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, base_directory, options=Namespace()):
|
def __init__(self, base_directory, options=Namespace(), plugins=None):
|
||||||
self._base_directory = base_directory
|
self._base_directory = base_directory
|
||||||
self._defaults = {}
|
self._defaults = {}
|
||||||
self._options = options
|
self._options = options
|
||||||
pass
|
self._plugins = plugins
|
||||||
|
|
||||||
def set_base_directory(self, base_directory):
|
def set_base_directory(self, base_directory):
|
||||||
self._base_directory = base_directory
|
self._base_directory = base_directory
|
||||||
|
@ -31,3 +31,7 @@ class Context:
|
||||||
|
|
||||||
def options(self):
|
def options(self):
|
||||||
return copy.deepcopy(self._options)
|
return copy.deepcopy(self._options)
|
||||||
|
|
||||||
|
def plugins(self):
|
||||||
|
# shallow copy is ok here
|
||||||
|
return copy.copy(self._plugins)
|
||||||
|
|
|
@ -17,18 +17,18 @@ class Dispatcher:
|
||||||
plugins=None,
|
plugins=None,
|
||||||
):
|
):
|
||||||
self._log = Messenger()
|
self._log = Messenger()
|
||||||
self._setup_context(base_directory, options)
|
self._setup_context(base_directory, options, plugins)
|
||||||
plugins = plugins or []
|
plugins = plugins or []
|
||||||
self._plugins = [plugin(self._context) for plugin in plugins]
|
self._plugins = [plugin(self._context) for plugin in plugins]
|
||||||
self._only = only
|
self._only = only
|
||||||
self._skip = skip
|
self._skip = skip
|
||||||
self._exit = exit_on_failure
|
self._exit = exit_on_failure
|
||||||
|
|
||||||
def _setup_context(self, base_directory, options):
|
def _setup_context(self, base_directory, options, plugins):
|
||||||
path = os.path.abspath(os.path.expanduser(base_directory))
|
path = os.path.abspath(os.path.expanduser(base_directory))
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
raise DispatchError("Nonexistent base directory")
|
raise DispatchError("Nonexistent base directory")
|
||||||
self._context = Context(path, options)
|
self._context = Context(path, options, plugins)
|
||||||
|
|
||||||
def dispatch(self, tasks):
|
def dispatch(self, tasks):
|
||||||
success = True
|
success = True
|
||||||
|
|
18
tests/dotbot_plugin_context_plugin.py
Normal file
18
tests/dotbot_plugin_context_plugin.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# https://github.com/anishathalye/dotbot/issues/339
|
||||||
|
# plugins should be able to instantiate a Dispatcher with all the plugins
|
||||||
|
|
||||||
|
import dotbot
|
||||||
|
from dotbot.dispatcher import Dispatcher
|
||||||
|
|
||||||
|
|
||||||
|
class Dispatch(dotbot.Plugin):
|
||||||
|
def can_handle(self, directive):
|
||||||
|
return directive == "dispatch"
|
||||||
|
|
||||||
|
def handle(self, directive, data):
|
||||||
|
dispatcher = Dispatcher(
|
||||||
|
base_directory=self._context.base_directory(),
|
||||||
|
options=self._context.options(),
|
||||||
|
plugins=self._context.plugins(),
|
||||||
|
)
|
||||||
|
return dispatcher.dispatch(data)
|
|
@ -170,3 +170,17 @@ def test_disable_builtin_plugins(home, dotfiles, run_dotbot):
|
||||||
run_dotbot("--disable-built-in-plugins")
|
run_dotbot("--disable-built-in-plugins")
|
||||||
|
|
||||||
assert not os.path.exists(os.path.join(home, ".f"))
|
assert not os.path.exists(os.path.join(home, ".f"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_plugin_context_plugin(capfd, home, dotfiles, run_dotbot):
|
||||||
|
"""Verify that the plugin context is available to plugins."""
|
||||||
|
|
||||||
|
plugin_file = os.path.join(
|
||||||
|
os.path.dirname(os.path.abspath(__file__)), "dotbot_plugin_context_plugin.py"
|
||||||
|
)
|
||||||
|
shutil.copy(plugin_file, os.path.join(dotfiles.directory, "plugin.py"))
|
||||||
|
dotfiles.write_config([{"dispatch": [{"shell": [{"command": "echo apple", "stdout": True}]}]}])
|
||||||
|
run_dotbot("--plugin", os.path.join(dotfiles.directory, "plugin.py"))
|
||||||
|
|
||||||
|
stdout = capfd.readouterr().out.splitlines()
|
||||||
|
assert any(line.startswith("apple") for line in stdout)
|
||||||
|
|
Loading…
Reference in a new issue