Make Dispatcher have all plugins by default
This used to be the behavior, and thenb5499c7dc5
changed this, breaking some plugins (some of which subsequently implemented workarounds). This patch restores the behavior, so that if a Dispatcher is constructed without explicitly passing in plugins, it has access to all plugins. This change seems safe, in that it's unlikely that any plugins were relying on the behavior betweenb5499c7dc5
and this patch, where a Dispatcher without an explicit plugin list behaved as if there were no plugins---because such a Dispatcher is not very useful!
This commit is contained in:
parent
6489f28311
commit
def05688c0
4 changed files with 46 additions and 2 deletions
|
@ -7,7 +7,7 @@ from argparse import ArgumentParser, RawTextHelpFormatter
|
||||||
import dotbot
|
import dotbot
|
||||||
|
|
||||||
from .config import ConfigReader, ReadingError
|
from .config import ConfigReader, ReadingError
|
||||||
from .dispatcher import Dispatcher, DispatchError
|
from .dispatcher import Dispatcher, DispatchError, _all_plugins
|
||||||
from .messenger import Level, Messenger
|
from .messenger import Level, Messenger
|
||||||
from .plugins import Clean, Create, Link, Shell
|
from .plugins import Clean, Create, Link, Shell
|
||||||
from .util import module
|
from .util import module
|
||||||
|
@ -151,6 +151,7 @@ def main():
|
||||||
# default to directory of config file
|
# default to directory of config file
|
||||||
base_directory = os.path.dirname(os.path.abspath(options.config_file))
|
base_directory = os.path.dirname(os.path.abspath(options.config_file))
|
||||||
os.chdir(base_directory)
|
os.chdir(base_directory)
|
||||||
|
_all_plugins[:] = plugins # for backwards compatibility, see dispatcher.py
|
||||||
dispatcher = Dispatcher(
|
dispatcher = Dispatcher(
|
||||||
base_directory,
|
base_directory,
|
||||||
only=options.only,
|
only=options.only,
|
||||||
|
|
|
@ -5,6 +5,14 @@ from .context import Context
|
||||||
from .messenger import Messenger
|
from .messenger import Messenger
|
||||||
from .plugin import Plugin
|
from .plugin import Plugin
|
||||||
|
|
||||||
|
# Before b5499c7dc5b300462f3ce1c2a3d9b7a76233b39b, Dispatcher auto-loaded all
|
||||||
|
# plugins, but after that change, plugins are passed in explicitly (and loaded
|
||||||
|
# in cli.py). There are some plugins that rely on the old Dispatcher behavior,
|
||||||
|
# so this is a workaround for implementing similar functionality: when
|
||||||
|
# Dispatcher is constructed without an explicit list of plugins, _all_plugins is
|
||||||
|
# used instead.
|
||||||
|
_all_plugins = [] # filled in by cli.py
|
||||||
|
|
||||||
|
|
||||||
class Dispatcher:
|
class Dispatcher:
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -16,9 +24,12 @@ class Dispatcher:
|
||||||
options=Namespace(),
|
options=Namespace(),
|
||||||
plugins=None,
|
plugins=None,
|
||||||
):
|
):
|
||||||
|
# if the caller wants no plugins, the caller needs to explicitly pass in
|
||||||
|
# plugins=[]
|
||||||
self._log = Messenger()
|
self._log = Messenger()
|
||||||
self._setup_context(base_directory, options, plugins)
|
self._setup_context(base_directory, options, plugins)
|
||||||
plugins = plugins or []
|
if plugins is None:
|
||||||
|
plugins = _all_plugins
|
||||||
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
|
||||||
|
|
18
tests/dotbot_plugin_dispatcher_no_plugins.py
Normal file
18
tests/dotbot_plugin_dispatcher_no_plugins.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# https://github.com/anishathalye/dotbot/issues/339, https://github.com/anishathalye/dotbot/pull/332
|
||||||
|
# if plugins instantiate a Dispatcher without explicitly passing in plugins,
|
||||||
|
# the Dispatcher should have access to all plugins (matching context.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(),
|
||||||
|
)
|
||||||
|
return dispatcher.dispatch(data)
|
|
@ -199,3 +199,17 @@ def test_plugin_context_plugin(capfd, home, dotfiles, run_dotbot):
|
||||||
|
|
||||||
stdout = capfd.readouterr().out.splitlines()
|
stdout = capfd.readouterr().out.splitlines()
|
||||||
assert any(line.startswith("apple") for line in stdout)
|
assert any(line.startswith("apple") for line in stdout)
|
||||||
|
|
||||||
|
|
||||||
|
def test_plugin_dispatcher_no_plugins(capfd, home, dotfiles, run_dotbot):
|
||||||
|
"""Verify that plugins instantiating Dispatcher without plugins work."""
|
||||||
|
|
||||||
|
plugin_file = os.path.join(
|
||||||
|
os.path.dirname(os.path.abspath(__file__)), "dotbot_plugin_dispatcher_no_plugins.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