diff --git a/qutebrowser/extensions/loader.py b/qutebrowser/extensions/loader.py index be7beeb11..338449c5b 100644 --- a/qutebrowser/extensions/loader.py +++ b/qutebrowser/extensions/loader.py @@ -65,6 +65,7 @@ class ModuleInfo: _ConfigChangedHooksType = typing.List[typing.Tuple[typing.Optional[str], typing.Callable]] + skip_hooks = attr.ib(False) # type: bool init_hook = attr.ib(None) # type: typing.Optional[typing.Callable] config_changed_hooks = attr.ib( attr.Factory(list)) # type: _ConfigChangedHooksType @@ -86,10 +87,10 @@ def add_module_info(module: types.ModuleType) -> ModuleInfo: return module.__qute_module_info # type: ignore -def load_components() -> None: +def load_components(*, skip_hooks=False) -> None: """Load everything from qutebrowser.components.""" for info in walk_components(): - _load_component(info) + _load_component(info, skip_hooks=skip_hooks) def walk_components() -> typing.Iterator[ExtensionInfo]: @@ -141,13 +142,21 @@ def _get_init_context() -> InitContext: args=objreg.get('args')) -def _load_component(info: ExtensionInfo) -> types.ModuleType: - """Load the given extension and run its init hook (if any).""" +def _load_component(info: ExtensionInfo, *, skip_hooks) -> types.ModuleType: + """Load the given extension and run its init hook (if any). + + Args: + skip_hooks: Whether to skip all hooks for this module. + This is used to only run @cmdutils.register decorators. + """ log.extensions.debug("Importing {}".format(info.name)) mod = importlib.import_module(info.name) mod_info = add_module_info(mod) - if mod_info.init_hook is not None: + if skip_hooks: + mod_info.skip_hooks = True + + if mod_info.init_hook is not None and not skip_hooks: log.extensions.debug("Running init hook {!r}" .format(mod_info.init_hook.__name__)) mod_info.init_hook(_get_init_context()) @@ -161,6 +170,8 @@ def _load_component(info: ExtensionInfo) -> types.ModuleType: def _on_config_changed(changed_name: str) -> None: """Call config_changed hooks if the config changed.""" for mod_info in _module_infos: + if mod_info.skip_hooks: + continue for option, hook in mod_info.config_changed_hooks: if option is None: hook() diff --git a/scripts/dev/run_vulture.py b/scripts/dev/run_vulture.py index 7874f6a79..51662f3c9 100755 --- a/scripts/dev/run_vulture.py +++ b/scripts/dev/run_vulture.py @@ -44,7 +44,7 @@ from qutebrowser.config import configtypes def whitelist_generator(): # noqa """Generator which yields lines to add to a vulture whitelist.""" - loader.load_components() + loader.load_components(skip_hooks=True) # qutebrowser commands for cmd in objects.commands.values(): diff --git a/scripts/dev/src2asciidoc.py b/scripts/dev/src2asciidoc.py index f0536c045..1ba272fba 100755 --- a/scripts/dev/src2asciidoc.py +++ b/scripts/dev/src2asciidoc.py @@ -550,7 +550,7 @@ def regenerate_cheatsheet(): def main(): """Regenerate all documentation.""" utils.change_cwd() - loader.load_components() + loader.load_components(skip_hooks=True) print("Generating manpage...") regenerate_manpage('doc/qutebrowser.1.asciidoc') print("Generating settings help...") diff --git a/tests/unit/extensions/test_loader.py b/tests/unit/extensions/test_loader.py index e0c1912fa..710b1ce9c 100644 --- a/tests/unit/extensions/test_loader.py +++ b/tests/unit/extensions/test_loader.py @@ -43,7 +43,7 @@ def test_load_component(monkeypatch): monkeypatch.setattr(objects, 'commands', {}) info = loader.ExtensionInfo(name='qutebrowser.components.scrollcommands') - module = loader._load_component(info) + module = loader._load_component(info, skip_hooks=True) assert hasattr(module, 'scroll_to_perc') assert 'scroll-to-perc' in objects.commands