Add setdefault option to tcl module (#14686)

This commit introduces the command

spack module tcl setdefault <package>

similar to the one already available for lmod

Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
This commit is contained in:
victorusu 2021-12-17 10:05:32 +01:00 committed by Massimiliano Culpo
parent 79fd1c5114
commit 17edf1ae90
5 changed files with 79 additions and 19 deletions

View File

@ -4,12 +4,11 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import functools import functools
import os
import llnl.util.filesystem
import spack.cmd.common.arguments import spack.cmd.common.arguments
import spack.cmd.modules import spack.cmd.modules
import spack.config
import spack.modules.lmod
def add_command(parser, command_dict): 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 # https://lmod.readthedocs.io/en/latest/060_locating.html#marking-a-version-as-default
# #
spack.cmd.modules.one_spec_or_raise(specs) spack.cmd.modules.one_spec_or_raise(specs)
writer = spack.modules.module_types['lmod']( spec = specs[0]
specs[0], args.module_set_name) data = {
'modules': {
module_folder = os.path.dirname(writer.layout.filename) args.module_set_name: {
module_basename = os.path.basename(writer.layout.filename) 'lmod': {
with llnl.util.filesystem.working_dir(module_folder): 'defaults': [str(spec)]
if os.path.exists('default') and os.path.islink('default'): }
os.remove('default') }
os.symlink(module_basename, 'default') }
}
# 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()

View File

@ -2,18 +2,52 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details. # Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import functools import functools
import spack.cmd.common.arguments
import spack.cmd.modules import spack.cmd.modules
import spack.config
import spack.modules.tcl
def add_command(parser, command_dict): def add_command(parser, command_dict):
tcl_parser = parser.add_parser( tcl_parser = parser.add_parser(
'tcl', help='manipulate non-hierarchical module files' '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( 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()

View File

@ -906,6 +906,9 @@ def write(self, overwrite=False):
fp.set_permissions_by_spec(self.layout.filename, self.spec) fp.set_permissions_by_spec(self.layout.filename, self.spec)
# Symlink defaults if needed # 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): if any(self.spec.satisfies(default) for default in self.conf.defaults):
# This spec matches a default, it needs to be symlinked to default # This spec matches a default, it needs to be symlinked to default
# Symlink to a tmp location first and move, so that existing # Symlink to a tmp location first and move, so that existing

View File

@ -178,10 +178,18 @@ def test_loads_recursive_blacklisted(database, module_configuration):
@pytest.mark.db @pytest.mark.db
def test_setdefault_command( 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 # Install two different versions of a package
other_spec, preferred = 'a@1.0', 'a@2.0' other_spec, preferred = 'a@1.0', 'a@2.0'

View File

@ -1382,7 +1382,7 @@ _spack_module_tcl() {
then then
SPACK_COMPREPLY="-h --help -n --name" SPACK_COMPREPLY="-h --help -n --name"
else else
SPACK_COMPREPLY="refresh find rm loads" SPACK_COMPREPLY="refresh find rm loads setdefault"
fi fi
} }
@ -1422,6 +1422,15 @@ _spack_module_tcl_loads() {
fi fi
} }
_spack_module_tcl_setdefault() {
if $list_options
then
SPACK_COMPREPLY="-h --help"
else
_installed_packages
fi
}
_spack_monitor() { _spack_monitor() {
SPACK_COMPREPLY="-h --help --monitor --monitor-save-local --monitor-no-auth --monitor-tags --monitor-keep-going --monitor-host --monitor-prefix" SPACK_COMPREPLY="-h --help --monitor --monitor-save-local --monitor-no-auth --monitor-tags --monitor-keep-going --monitor-host --monitor-prefix"
} }