diff options
-rw-r--r-- | lib/spack/docs/developer_guide.rst | 10 | ||||
-rw-r--r-- | lib/spack/spack/hooks/__init__.py | 47 |
2 files changed, 25 insertions, 32 deletions
diff --git a/lib/spack/docs/developer_guide.rst b/lib/spack/docs/developer_guide.rst index f538f75206..21204ba077 100644 --- a/lib/spack/docs/developer_guide.rst +++ b/lib/spack/docs/developer_guide.rst @@ -333,13 +333,9 @@ inserting them at different places in the spack code base. Whenever a hook type triggers by way of a function call, we find all the hooks of that type, and run them. -Spack defines hooks by way of a module at ``lib/spack/spack/hooks`` where we can define -types of hooks in the ``__init__.py``, and then python files in that folder -can use hook functions. The files are automatically parsed, so if you write -a new file for some integration (e.g., ``lib/spack/spack/hooks/myintegration.py`` -you can then write hook functions in that file that will be automatically detected, -and run whenever your hook is called. This section will cover the basic kind -of hooks, and how to write them. +Spack defines hooks by way of a module in the ``lib/spack/spack/hooks`` directory. +This module has to be registered in ``__init__.py`` so that Spack is aware of it. +This section will cover the basic kind of hooks, and how to write them. ^^^^^^^^^^^^^^ Types of Hooks diff --git a/lib/spack/spack/hooks/__init__.py b/lib/spack/spack/hooks/__init__.py index 0e7e303692..73fad62d6a 100644 --- a/lib/spack/spack/hooks/__init__.py +++ b/lib/spack/spack/hooks/__init__.py @@ -21,43 +21,40 @@ systems (e.g. modules, lmod, etc.) or to add other custom features. """ import importlib - -from llnl.util.lang import ensure_last, list_modules - -import spack.paths +import types +from typing import List, Optional class _HookRunner: - #: Stores all hooks on first call, shared among - #: all HookRunner objects - _hooks = None + #: Order in which hooks are executed + HOOK_ORDER = [ + "spack.hooks.module_file_generation", + "spack.hooks.licensing", + "spack.hooks.sbang", + "spack.hooks.windows_runtime_linkage", + "spack.hooks.drop_redundant_rpaths", + "spack.hooks.absolutify_elf_sonames", + "spack.hooks.permissions_setters", + # after all mutations to the install prefix, write metadata + "spack.hooks.write_install_manifest", + # after all metadata is written + "spack.hooks.autopush", + ] + + #: Contains all hook modules after first call, shared among all HookRunner objects + _hooks: Optional[List[types.ModuleType]] = None def __init__(self, hook_name): self.hook_name = hook_name - @classmethod - def _populate_hooks(cls): - # Lazily populate the list of hooks - cls._hooks = [] - - relative_names = list(list_modules(spack.paths.hooks_path)) - - # Ensure that write_install_manifest comes last - ensure_last(relative_names, "absolutify_elf_sonames", "write_install_manifest") - - for name in relative_names: - module_name = __name__ + "." + name - module_obj = importlib.import_module(module_name) - cls._hooks.append((module_name, module_obj)) - @property - def hooks(self): + def hooks(self) -> List[types.ModuleType]: if not self._hooks: - self._populate_hooks() + self._hooks = [importlib.import_module(module_name) for module_name in self.HOOK_ORDER] return self._hooks def __call__(self, *args, **kwargs): - for _, module in self.hooks: + for module in self.hooks: if hasattr(module, self.hook_name): hook = getattr(module, self.hook_name) if hasattr(hook, "__call__"): |