Make Dispatcher a singleton after first instantiation
This allows plugins to re-instantiate the Dispatcher (or, now, use the instance cached in `current_dispatcher`) without knowing what plugins have been loaded by dotbot. This fixes plugins that want to dispatch to other plugins. Fixes #339
This commit is contained in:
parent
840cd164d2
commit
25497721a3
3 changed files with 47 additions and 0 deletions
|
@ -5,8 +5,23 @@ from .context import Context
|
|||
from .messenger import Messenger
|
||||
from .plugin import Plugin
|
||||
|
||||
current_dispatcher = None
|
||||
|
||||
|
||||
class Dispatcher:
|
||||
def __new__(cls, *args, **kwargs):
|
||||
# After dotbot instantiates this class, the instance will be cached.
|
||||
# Subsequent instantiations (say, by plugins) will return the same instance.
|
||||
# This is needed because plugins don't have access to the entire configuration
|
||||
# (for example, they won't know which plugins have been loaded).
|
||||
# This ensures a consistent configuration is used.
|
||||
global current_dispatcher
|
||||
if current_dispatcher is None:
|
||||
instance = object.__new__(cls)
|
||||
instance.is_initialized = False
|
||||
current_dispatcher = instance
|
||||
return current_dispatcher
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
base_directory,
|
||||
|
@ -16,6 +31,9 @@ class Dispatcher:
|
|||
options=Namespace(),
|
||||
plugins=None,
|
||||
):
|
||||
if self.is_initialized:
|
||||
return
|
||||
self.is_initialized = True
|
||||
self._log = Messenger()
|
||||
self._setup_context(base_directory, options)
|
||||
plugins = plugins or []
|
||||
|
|
|
@ -12,6 +12,7 @@ import pytest
|
|||
import yaml
|
||||
|
||||
import dotbot.cli
|
||||
import dotbot.dispatcher
|
||||
|
||||
|
||||
def get_long_path(path):
|
||||
|
@ -312,3 +313,9 @@ def run_dotbot(dotfiles):
|
|||
dotbot.cli.main()
|
||||
|
||||
yield runner
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def reset_current_dispatcher():
|
||||
yield
|
||||
dotbot.dispatcher.current_dispatcher = None
|
||||
|
|
22
tests/test_dispatcher.py
Normal file
22
tests/test_dispatcher.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
import dotbot.dispatcher
|
||||
|
||||
|
||||
def test_dispatcher_instantiation(home, dotfiles, run_dotbot):
|
||||
"""Verify that the dispatcher caches itself as a singleton."""
|
||||
|
||||
assert dotbot.dispatcher.current_dispatcher is None
|
||||
|
||||
dotfiles.write_config([])
|
||||
run_dotbot()
|
||||
|
||||
# Verify the dispatcher has been cached.
|
||||
assert dotbot.dispatcher.current_dispatcher is not None
|
||||
|
||||
existing_id = id(dotbot.dispatcher.current_dispatcher)
|
||||
new_instance = dotbot.dispatcher.Dispatcher("bogus")
|
||||
|
||||
# Verify the new and existing instances are the same.
|
||||
assert existing_id == id(new_instance)
|
||||
|
||||
# Verify the singleton was not overridden.
|
||||
assert existing_id == id(dotbot.dispatcher.current_dispatcher)
|
Loading…
Reference in a new issue