module : can regenerate single module files, homogenized cli options
spack module : - refresh accepts a constraint - find and refresh share common cli options - ask for confirmation before refreshing - deleting the module file tree is now optional
This commit is contained in:
parent
0fd58fb585
commit
b71d430af6
4 changed files with 101 additions and 59 deletions
|
@ -32,73 +32,115 @@
|
||||||
from spack.modules import module_types
|
from spack.modules import module_types
|
||||||
from spack.util.string import *
|
from spack.util.string import *
|
||||||
|
|
||||||
description = "Manipulate modules and dotkits."
|
from spack.cmd.uninstall import ask_for_confirmation
|
||||||
|
|
||||||
|
description = "Manipulate module files"
|
||||||
|
|
||||||
|
|
||||||
|
def _add_common_arguments(subparser):
|
||||||
|
type_help = 'Type of module files'
|
||||||
|
subparser.add_argument('--module-type', help=type_help, required=True, choices=module_types)
|
||||||
|
constraint_help = 'Optional constraint to select a subset of installed packages'
|
||||||
|
subparser.add_argument('constraint', nargs='*', help=constraint_help)
|
||||||
|
|
||||||
|
|
||||||
def setup_parser(subparser):
|
def setup_parser(subparser):
|
||||||
sp = subparser.add_subparsers(metavar='SUBCOMMAND', dest='module_command')
|
sp = subparser.add_subparsers(metavar='SUBCOMMAND', dest='module_command')
|
||||||
|
# spack module refresh
|
||||||
|
refresh_parser = sp.add_parser('refresh', help='Regenerate all module files.')
|
||||||
|
refresh_parser.add_argument('--delete-tree', help='Delete the module file tree before refresh', action='store_true')
|
||||||
|
_add_common_arguments(refresh_parser)
|
||||||
|
|
||||||
sp.add_parser('refresh', help='Regenerate all module files.')
|
# spack module find
|
||||||
|
|
||||||
find_parser = sp.add_parser('find', help='Find module files for packages.')
|
find_parser = sp.add_parser('find', help='Find module files for packages.')
|
||||||
find_parser.add_argument('module_type',
|
_add_common_arguments(find_parser)
|
||||||
help="Type of module to find file for. [" +
|
|
||||||
'|'.join(module_types) + "]")
|
|
||||||
find_parser.add_argument('spec',
|
|
||||||
nargs='+',
|
|
||||||
help='spec to find a module file for.')
|
|
||||||
|
|
||||||
|
|
||||||
def module_find(mtype, spec_array):
|
class MultipleMatches(Exception):
|
||||||
"""Look at all installed packages and see if the spec provided
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NoMatch(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def module_find(mtype, specs, args):
|
||||||
|
"""
|
||||||
|
Look at all installed packages and see if the spec provided
|
||||||
matches any. If it does, check whether there is a module file
|
matches any. If it does, check whether there is a module file
|
||||||
of type <mtype> there, and print out the name that the user
|
of type <mtype> there, and print out the name that the user
|
||||||
should type to use that package's module.
|
should type to use that package's module.
|
||||||
"""
|
"""
|
||||||
if mtype not in module_types:
|
|
||||||
tty.die("Invalid module type: '%s'. Options are %s" %
|
|
||||||
(mtype, comma_or(module_types)))
|
|
||||||
|
|
||||||
specs = spack.cmd.parse_specs(spec_array)
|
|
||||||
if len(specs) > 1:
|
|
||||||
tty.die("You can only pass one spec.")
|
|
||||||
spec = specs[0]
|
|
||||||
|
|
||||||
specs = spack.installed_db.query(spec)
|
|
||||||
if len(specs) == 0:
|
if len(specs) == 0:
|
||||||
tty.die("No installed packages match spec %s" % spec)
|
raise NoMatch()
|
||||||
|
|
||||||
if len(specs) > 1:
|
if len(specs) > 1:
|
||||||
tty.error("Multiple matches for spec %s. Choose one:" % spec)
|
raise MultipleMatches()
|
||||||
for s in specs:
|
|
||||||
sys.stderr.write(s.tree(color=True))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
mt = module_types[mtype]
|
mod = module_types[mtype](specs.pop())
|
||||||
mod = mt(specs[0])
|
|
||||||
if not os.path.isfile(mod.file_name):
|
if not os.path.isfile(mod.file_name):
|
||||||
tty.die("No %s module is installed for %s" % (mtype, spec))
|
tty.die("No %s module is installed for %s" % (mtype, spec))
|
||||||
|
|
||||||
print(mod.use_name)
|
print(mod.use_name)
|
||||||
|
|
||||||
|
|
||||||
def module_refresh():
|
def module_refresh(name, specs, args):
|
||||||
"""Regenerate all module files for installed packages known to
|
"""
|
||||||
spack (some packages may no longer exist)."""
|
Regenerate all module files for installed packages known to
|
||||||
specs = [s for s in spack.installed_db.query(installed=True, known=True)]
|
spack (some packages may no longer exist).
|
||||||
|
"""
|
||||||
|
# Prompt a message to the user about what is going to change
|
||||||
|
if not specs:
|
||||||
|
tty.msg('No package matches your query')
|
||||||
|
return
|
||||||
|
|
||||||
for name, cls in module_types.items():
|
tty.msg('You are about to regenerate the {name} module files for the following specs:'.format(name=name))
|
||||||
tty.msg("Regenerating %s module files." % name)
|
for s in specs:
|
||||||
if os.path.isdir(cls.path):
|
print(s.format(color=True))
|
||||||
|
ask_for_confirmation('Do you want to proceed ? ')
|
||||||
|
|
||||||
|
cls = module_types[name]
|
||||||
|
tty.msg('Regenerating {name} module files'.format(name=name))
|
||||||
|
if os.path.isdir(cls.path) and args.delete_tree:
|
||||||
shutil.rmtree(cls.path, ignore_errors=False)
|
shutil.rmtree(cls.path, ignore_errors=False)
|
||||||
mkdirp(cls.path)
|
mkdirp(cls.path)
|
||||||
for spec in specs:
|
for spec in specs:
|
||||||
cls(spec).write()
|
cls(spec).write()
|
||||||
|
|
||||||
|
# Qualifiers to be used when querying the db for specs
|
||||||
|
constraint_qualifiers = {
|
||||||
|
'refresh': {
|
||||||
|
'installed': True,
|
||||||
|
'known': True
|
||||||
|
},
|
||||||
|
'find': {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Dictionary of callbacks based on the value of module_command
|
||||||
|
callbacks = {
|
||||||
|
'refresh': module_refresh,
|
||||||
|
'find': module_find
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def module(parser, args):
|
def module(parser, args):
|
||||||
if args.module_command == 'refresh':
|
module_type = args.module_type
|
||||||
module_refresh()
|
# Query specs from command line
|
||||||
|
qualifiers = constraint_qualifiers[args.module_command]
|
||||||
elif args.module_command == 'find':
|
specs = [s for s in spack.installed_db.query(**qualifiers)]
|
||||||
module_find(args.module_type, args.spec)
|
constraint = ' '.join(args.constraint)
|
||||||
|
if constraint:
|
||||||
|
specs = [x for x in specs if x.satisfies(constraint, strict=True)]
|
||||||
|
# Call the appropriate function
|
||||||
|
try:
|
||||||
|
callbacks[args.module_command](module_type, specs, args)
|
||||||
|
except MultipleMatches:
|
||||||
|
message = 'the constraint \'{query}\' matches multiple packages, and this is not allowed in this context'
|
||||||
|
tty.error(message.format(query=constraint))
|
||||||
|
for s in specs:
|
||||||
|
sys.stderr.write(s.format(color=True) + '\n')
|
||||||
|
raise SystemExit(1)
|
||||||
|
except NoMatch:
|
||||||
|
message = 'the constraint \'{query}\' match no package, and this is not allowed in this context'
|
||||||
|
tty.die(message.format(query=constraint))
|
||||||
|
|
|
@ -454,7 +454,7 @@ def remove(self):
|
||||||
|
|
||||||
class Dotkit(EnvModule):
|
class Dotkit(EnvModule):
|
||||||
name = 'dotkit'
|
name = 'dotkit'
|
||||||
|
path = join_path(spack.share_path, 'dotkit')
|
||||||
environment_modifications_formats = {
|
environment_modifications_formats = {
|
||||||
PrependPath: 'dk_alter {name} {value}\n',
|
PrependPath: 'dk_alter {name} {value}\n',
|
||||||
SetEnv: 'dk_setenv {name} {value}\n'
|
SetEnv: 'dk_setenv {name} {value}\n'
|
||||||
|
@ -466,7 +466,7 @@ class Dotkit(EnvModule):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def file_name(self):
|
def file_name(self):
|
||||||
return join_path(spack.share_path, "dotkit", self.spec.architecture,
|
return join_path(self.path, self.spec.architecture,
|
||||||
'%s.dk' % self.use_name)
|
'%s.dk' % self.use_name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -494,7 +494,7 @@ def prerequisite(self, spec):
|
||||||
|
|
||||||
class TclModule(EnvModule):
|
class TclModule(EnvModule):
|
||||||
name = 'tcl'
|
name = 'tcl'
|
||||||
|
path = join_path(spack.share_path, "modules")
|
||||||
environment_modifications_formats = {
|
environment_modifications_formats = {
|
||||||
PrependPath: 'prepend-path --delim "{delim}" {name} \"{value}\"\n',
|
PrependPath: 'prepend-path --delim "{delim}" {name} \"{value}\"\n',
|
||||||
AppendPath: 'append-path --delim "{delim}" {name} \"{value}\"\n',
|
AppendPath: 'append-path --delim "{delim}" {name} \"{value}\"\n',
|
||||||
|
@ -514,7 +514,7 @@ class TclModule(EnvModule):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def file_name(self):
|
def file_name(self):
|
||||||
return join_path(spack.share_path, "modules", self.spec.architecture, self.use_name)
|
return join_path(self.path, self.spec.architecture, self.use_name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def header(self):
|
def header(self):
|
||||||
|
|
|
@ -74,25 +74,25 @@ case unload:
|
||||||
# tool's commands to add/remove the result from the environment.
|
# tool's commands to add/remove the result from the environment.
|
||||||
switch ($_sp_subcommand)
|
switch ($_sp_subcommand)
|
||||||
case "use":
|
case "use":
|
||||||
set _sp_full_spec = ( "`\spack $_sp_flags module find dotkit $_sp_spec`" )
|
set _sp_full_spec = ( "`\spack $_sp_flags module find --module-type dotkit $_sp_spec`" )
|
||||||
if ( $? == 0 ) then
|
if ( $? == 0 ) then
|
||||||
use $_sp_module_args $_sp_full_spec
|
use $_sp_module_args $_sp_full_spec
|
||||||
endif
|
endif
|
||||||
breaksw
|
breaksw
|
||||||
case "unuse":
|
case "unuse":
|
||||||
set _sp_full_spec = ( "`\spack $_sp_flags module find dotkit $_sp_spec`" )
|
set _sp_full_spec = ( "`\spack $_sp_flags module find --module-type dotkit $_sp_spec`" )
|
||||||
if ( $? == 0 ) then
|
if ( $? == 0 ) then
|
||||||
unuse $_sp_module_args $_sp_full_spec
|
unuse $_sp_module_args $_sp_full_spec
|
||||||
endif
|
endif
|
||||||
breaksw
|
breaksw
|
||||||
case "load":
|
case "load":
|
||||||
set _sp_full_spec = ( "`\spack $_sp_flags module find tcl $_sp_spec`" )
|
set _sp_full_spec = ( "`\spack $_sp_flags module find --module-type tcl $_sp_spec`" )
|
||||||
if ( $? == 0 ) then
|
if ( $? == 0 ) then
|
||||||
module load $_sp_module_args $_sp_full_spec
|
module load $_sp_module_args $_sp_full_spec
|
||||||
endif
|
endif
|
||||||
breaksw
|
breaksw
|
||||||
case "unload":
|
case "unload":
|
||||||
set _sp_full_spec = ( "`\spack $_sp_flags module find tcl $_sp_spec`" )
|
set _sp_full_spec = ( "`\spack $_sp_flags module find --module-type tcl $_sp_spec`" )
|
||||||
if ( $? == 0 ) then
|
if ( $? == 0 ) then
|
||||||
module unload $_sp_module_args $_sp_full_spec
|
module unload $_sp_module_args $_sp_full_spec
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -105,19 +105,19 @@ function spack {
|
||||||
# If spack module command comes back with an error, do nothing.
|
# If spack module command comes back with an error, do nothing.
|
||||||
case $_sp_subcommand in
|
case $_sp_subcommand in
|
||||||
"use")
|
"use")
|
||||||
if _sp_full_spec=$(command spack $_sp_flags module find dotkit $_sp_spec); then
|
if _sp_full_spec=$(command spack $_sp_flags module find --module-type dotkit $_sp_spec); then
|
||||||
use $_sp_module_args $_sp_full_spec
|
use $_sp_module_args $_sp_full_spec
|
||||||
fi ;;
|
fi ;;
|
||||||
"unuse")
|
"unuse")
|
||||||
if _sp_full_spec=$(command spack $_sp_flags module find dotkit $_sp_spec); then
|
if _sp_full_spec=$(command spack $_sp_flags module find --module-type dotkit $_sp_spec); then
|
||||||
unuse $_sp_module_args $_sp_full_spec
|
unuse $_sp_module_args $_sp_full_spec
|
||||||
fi ;;
|
fi ;;
|
||||||
"load")
|
"load")
|
||||||
if _sp_full_spec=$(command spack $_sp_flags module find tcl $_sp_spec); then
|
if _sp_full_spec=$(command spack $_sp_flags module find --module-type tcl $_sp_spec); then
|
||||||
module load $_sp_module_args $_sp_full_spec
|
module load $_sp_module_args $_sp_full_spec
|
||||||
fi ;;
|
fi ;;
|
||||||
"unload")
|
"unload")
|
||||||
if _sp_full_spec=$(command spack $_sp_flags module find tcl $_sp_spec); then
|
if _sp_full_spec=$(command spack $_sp_flags module find --module-type tcl $_sp_spec); then
|
||||||
module unload $_sp_module_args $_sp_full_spec
|
module unload $_sp_module_args $_sp_full_spec
|
||||||
fi ;;
|
fi ;;
|
||||||
esac
|
esac
|
||||||
|
|
Loading…
Reference in a new issue