From 17edf1ae90a9b56eb50ec002027a424bef58d97d Mon Sep 17 00:00:00 2001 From: victorusu Date: Fri, 17 Dec 2021 10:05:32 +0100 Subject: Add setdefault option to tcl module (#14686) This commit introduces the command spack module tcl setdefault similar to the one already available for lmod Co-authored-by: Massimiliano Culpo --- lib/spack/spack/cmd/modules/lmod.py | 30 +++++++++++++++++----------- lib/spack/spack/cmd/modules/tcl.py | 40 ++++++++++++++++++++++++++++++++++--- lib/spack/spack/modules/common.py | 3 +++ lib/spack/spack/test/cmd/module.py | 14 ++++++++++--- share/spack/spack-completion.bash | 11 +++++++++- 5 files changed, 79 insertions(+), 19 deletions(-) diff --git a/lib/spack/spack/cmd/modules/lmod.py b/lib/spack/spack/cmd/modules/lmod.py index d28ccb3eaf..1920f8ec66 100644 --- a/lib/spack/spack/cmd/modules/lmod.py +++ b/lib/spack/spack/cmd/modules/lmod.py @@ -4,12 +4,11 @@ # SPDX-License-Identifier: (Apache-2.0 OR MIT) import functools -import os - -import llnl.util.filesystem import spack.cmd.common.arguments import spack.cmd.modules +import spack.config +import spack.modules.lmod def add_command(parser, command_dict): @@ -41,12 +40,19 @@ def setdefault(module_type, specs, args): # https://lmod.readthedocs.io/en/latest/060_locating.html#marking-a-version-as-default # spack.cmd.modules.one_spec_or_raise(specs) - writer = spack.modules.module_types['lmod']( - specs[0], args.module_set_name) - - module_folder = os.path.dirname(writer.layout.filename) - module_basename = os.path.basename(writer.layout.filename) - with llnl.util.filesystem.working_dir(module_folder): - if os.path.exists('default') and os.path.islink('default'): - os.remove('default') - os.symlink(module_basename, 'default') + spec = specs[0] + data = { + 'modules': { + args.module_set_name: { + 'lmod': { + 'defaults': [str(spec)] + } + } + } + } + # Need to clear the cache if a SpackCommand is called during scripting + spack.modules.lmod.configuration_registry = {} + scope = spack.config.InternalConfigScope('lmod-setdefault', data) + with spack.config.override(scope): + writer = spack.modules.module_types['lmod'](spec, args.module_set_name) + writer.update_module_defaults() diff --git a/lib/spack/spack/cmd/modules/tcl.py b/lib/spack/spack/cmd/modules/tcl.py index a9486b9de4..5a29bc6df5 100644 --- a/lib/spack/spack/cmd/modules/tcl.py +++ b/lib/spack/spack/cmd/modules/tcl.py @@ -2,18 +2,52 @@ # Spack Project Developers. See the top-level COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) - import functools +import spack.cmd.common.arguments import spack.cmd.modules +import spack.config +import spack.modules.tcl def add_command(parser, command_dict): tcl_parser = parser.add_parser( 'tcl', help='manipulate non-hierarchical module files' ) - spack.cmd.modules.setup_parser(tcl_parser) + sp = spack.cmd.modules.setup_parser(tcl_parser) + + # Set default module file for a package + setdefault_parser = sp.add_parser( + 'setdefault', help='set the default module file for a package' + ) + spack.cmd.common.arguments.add_common_arguments( + setdefault_parser, ['constraint'] + ) + + callbacks = dict(spack.cmd.modules.callbacks.items()) + callbacks['setdefault'] = setdefault command_dict['tcl'] = functools.partial( - spack.cmd.modules.modules_cmd, module_type='tcl' + spack.cmd.modules.modules_cmd, module_type='tcl', callbacks=callbacks ) + + +def setdefault(module_type, specs, args): + """Set the default module file, when multiple are present""" + # Currently, accepts only a single matching spec + spack.cmd.modules.one_spec_or_raise(specs) + spec = specs[0] + data = { + 'modules': { + args.module_set_name: { + 'tcl': { + 'defaults': [str(spec)] + } + } + } + } + spack.modules.tcl.configuration_registry = {} + scope = spack.config.InternalConfigScope('tcl-setdefault', data) + with spack.config.override(scope): + writer = spack.modules.module_types['tcl'](spec, args.module_set_name) + writer.update_module_defaults() diff --git a/lib/spack/spack/modules/common.py b/lib/spack/spack/modules/common.py index 8855e57e64..aee1c1cc17 100644 --- a/lib/spack/spack/modules/common.py +++ b/lib/spack/spack/modules/common.py @@ -906,6 +906,9 @@ class BaseModuleFileWriter(object): fp.set_permissions_by_spec(self.layout.filename, self.spec) # Symlink defaults if needed + self.update_module_defaults() + + def update_module_defaults(self): if any(self.spec.satisfies(default) for default in self.conf.defaults): # This spec matches a default, it needs to be symlinked to default # Symlink to a tmp location first and move, so that existing diff --git a/lib/spack/spack/test/cmd/module.py b/lib/spack/spack/test/cmd/module.py index 3bced1d335..b157e1be6b 100644 --- a/lib/spack/spack/test/cmd/module.py +++ b/lib/spack/spack/test/cmd/module.py @@ -178,10 +178,18 @@ writer_cls = spack.modules.lmod.LmodModulefileWriter @pytest.mark.db def test_setdefault_command( - mutable_database, module_configuration + mutable_database, mutable_config ): - module_configuration('autoload_direct') - + data = { + 'default': { + 'enable': ['lmod'], + 'lmod': { + 'core_compilers': ['clang@3.3'], + 'hierarchy': ['mpi'] + } + } + } + spack.config.set('modules', data) # Install two different versions of a package other_spec, preferred = 'a@1.0', 'a@2.0' diff --git a/share/spack/spack-completion.bash b/share/spack/spack-completion.bash index c7e4d10197..b41a21946c 100755 --- a/share/spack/spack-completion.bash +++ b/share/spack/spack-completion.bash @@ -1382,7 +1382,7 @@ _spack_module_tcl() { then SPACK_COMPREPLY="-h --help -n --name" else - SPACK_COMPREPLY="refresh find rm loads" + SPACK_COMPREPLY="refresh find rm loads setdefault" fi } @@ -1422,6 +1422,15 @@ _spack_module_tcl_loads() { fi } +_spack_module_tcl_setdefault() { + if $list_options + then + SPACK_COMPREPLY="-h --help" + else + _installed_packages + fi +} + _spack_monitor() { SPACK_COMPREPLY="-h --help --monitor --monitor-save-local --monitor-no-auth --monitor-tags --monitor-keep-going --monitor-host --monitor-prefix" } -- cgit v1.2.3-70-g09d2