1
0
Fork 0
mirror of synced 2024-06-25 18:31:09 -04:00
dotbot/dotbot/dispatcher.py
Wouter Franken 8bd46a6549 Fix dispatcher when no plugins are given
When any plugin is using the dispatcher for nested actions it should
pass all plugins again to avoid that any plugin as subtask would be
handled.
Currently this means a lot of plugins are broken because they don't pass
plugins to the dispatcher.

To fix this, take all Plugin subclasses when no plugin is given (we
should at least have the default plugins).
2023-02-19 13:08:41 +01:00

82 lines
2.9 KiB
Python

import os
from argparse import Namespace
from .context import Context
from .messenger import Messenger
from .plugin import Plugin
class Dispatcher(object):
def __init__(
self,
base_directory,
only=None,
skip=None,
exit_on_failure=False,
options=Namespace(),
plugins=None,
):
self._log = Messenger()
self._setup_context(base_directory, options)
if plugins == None:
plugins = Plugin.__subclasses__()
else:
plugins = plugins or []
self._plugins = [plugin(self._context) for plugin in plugins]
self._only = only
self._skip = skip
self._exit = exit_on_failure
def _setup_context(self, base_directory, options):
path = os.path.abspath(os.path.expanduser(base_directory))
if not os.path.exists(path):
raise DispatchError("Nonexistent base directory")
self._context = Context(path, options)
def dispatch(self, tasks):
success = True
for task in tasks:
for action in task:
if (
self._only is not None
and action not in self._only
or self._skip is not None
and action in self._skip
) and action != "defaults":
self._log.info("Skipping action %s" % action)
continue
handled = False
if action == "defaults":
self._context.set_defaults(task[action]) # replace, not update
handled = True
# keep going, let other plugins handle this if they want
for plugin in self._plugins:
if plugin.can_handle(action):
try:
local_success = plugin.handle(action, task[action])
if not local_success and self._exit:
# The action has failed exit
self._log.error("Action %s failed" % action)
return False
success &= local_success
handled = True
except Exception as err:
self._log.error(
"An error was encountered while executing action %s" % action
)
self._log.debug(err)
if self._exit:
# There was an execption exit
return False
if not handled:
success = False
self._log.error("Action %s not handled" % action)
if self._exit:
# Invalid action exit
return False
return success
class DispatchError(Exception):
pass