1
0
Fork 0
mirror of synced 2024-12-04 13:25:34 -05:00

Compare commits

...

4 commits

Author SHA1 Message Date
Kurt McKee
5f4d9963d6
Merge 25497721a3 into 8d94c6ec1a 2024-11-28 23:53:32 +00:00
Anish Athalye
8d94c6ec1a Disable coverage status checks 2024-11-21 17:23:21 +05:30
Anish Athalye
2294ac78f8 Update actions 2024-11-21 17:13:19 +05:30
Kurt McKee
25497721a3
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
2023-09-10 10:08:41 -05:00
5 changed files with 56 additions and 2 deletions

View file

@ -47,11 +47,14 @@ jobs:
run: | run: |
python -m tox python -m tox
python -m tox -e coverage_report python -m tox -e coverage_report
- uses: codecov/codecov-action@v3 - uses: codecov/codecov-action@v5
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
fmt: fmt:
name: Format name: Format
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: psf/black@stable - uses: psf/black@stable
- uses: isort/isort-action@v1 - uses: isort/isort-action@v1

4
codecov.yml Normal file
View file

@ -0,0 +1,4 @@
coverage:
status:
project: off
patch: off

View file

@ -5,8 +5,23 @@ from .context import Context
from .messenger import Messenger from .messenger import Messenger
from .plugin import Plugin from .plugin import Plugin
current_dispatcher = None
class Dispatcher: 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__( def __init__(
self, self,
base_directory, base_directory,
@ -16,6 +31,9 @@ class Dispatcher:
options=Namespace(), options=Namespace(),
plugins=None, plugins=None,
): ):
if self.is_initialized:
return
self.is_initialized = True
self._log = Messenger() self._log = Messenger()
self._setup_context(base_directory, options) self._setup_context(base_directory, options)
plugins = plugins or [] plugins = plugins or []

View file

@ -12,6 +12,7 @@ import pytest
import yaml import yaml
import dotbot.cli import dotbot.cli
import dotbot.dispatcher
def get_long_path(path): def get_long_path(path):
@ -315,3 +316,9 @@ def run_dotbot(dotfiles):
dotbot.cli.main() dotbot.cli.main()
yield runner yield runner
@pytest.fixture(autouse=True)
def reset_current_dispatcher():
yield
dotbot.dispatcher.current_dispatcher = None

22
tests/test_dispatcher.py Normal file
View 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)