summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/cmd/module.py127
1 files changed, 88 insertions, 39 deletions
diff --git a/lib/spack/spack/cmd/module.py b/lib/spack/spack/cmd/module.py
index 5628ab17a5..6f9ede21ac 100644
--- a/lib/spack/spack/cmd/module.py
+++ b/lib/spack/spack/cmd/module.py
@@ -28,6 +28,7 @@ import os
import shutil
import sys
import collections
+import argparse
import llnl.util.tty as tty
import spack.cmd
@@ -40,33 +41,76 @@ from spack.cmd.uninstall import ask_for_confirmation
description = "Manipulate module files"
+# Qualifiers to be used when querying the db for specs
+constraint_qualifiers = {
+ 'refresh': {
+ 'installed': True,
+ 'known': True
+ },
+ 'find': {
+ },
+ 'load-list':{
+ },
+ 'rm': {
+ }
+}
+
+
+class ConstraintAction(argparse.Action):
+ qualifiers = {}
+
+ def __call__(self, parser, namespace, values, option_string=None):
+ # Query specs from command line
+ d = self.qualifiers.get(namespace.subparser_name, {})
+ specs = [s for s in spack.installed_db.query(**d)]
+ values = ' '.join(values)
+ if values:
+ specs = [x for x in specs if x.satisfies(values, strict=True)]
+ namespace.specs = specs
+
+# TODO : this needs better wrapping to be extracted
+ConstraintAction.qualifiers.update(constraint_qualifiers)
+
+
def _add_common_arguments(subparser):
type_help = 'Type of module files'
- subparser.add_argument('--module-type', help=type_help, default='tcl', choices=module_types)
+ subparser.add_argument('-m', '--module-type', help=type_help, default='tcl', choices=module_types)
constraint_help = 'Optional constraint to select a subset of installed packages'
- subparser.add_argument('constraint', nargs='*', help=constraint_help)
+ subparser.add_argument('constraint', nargs='*', help=constraint_help, action=ConstraintAction)
def setup_parser(subparser):
- sp = subparser.add_subparsers(metavar='SUBCOMMAND', dest='module_command')
+ sp = subparser.add_subparsers(metavar='SUBCOMMAND', dest='subparser_name')
# 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)
+ refresh_parser.add_argument(
+ '-y', '--yes-to-all', action='store_true', dest='yes_to_all',
+ help='Assume "yes" is the answer to every confirmation asked to the user.'
+ )
# spack module find
find_parser = sp.add_parser('find', help='Find module files for packages.')
_add_common_arguments(find_parser)
- # spack module env
+ # spack module rm
+ rm_parser = sp.add_parser('rm', help='Find module files for packages.')
+ _add_common_arguments(rm_parser)
+ rm_parser.add_argument(
+ '-y', '--yes-to-all', action='store_true', dest='yes_to_all',
+ help='Assume "yes" is the answer to every confirmation asked to the user.'
+ )
+
+ # spack module load-list
loadlist_parser = sp.add_parser(
'load-list',
help='Prompt the list of modules associated with packages that satisfy a contraint'
)
loadlist_parser.add_argument(
- '-r', '--dependencies', action='store_true',
+ '-d', '--dependencies', action='store_true',
dest='recurse_dependencies',
- help='Recursively traverse dependencies for modules to load.')
+ help='Recursively traverse spec dependencies')
loadlist_parser.add_argument(
'-s', '--shell', action='store_true', dest='shell',
@@ -87,7 +131,6 @@ class NoMatch(Exception):
def load_list(mtype, specs, args):
-
# Get a comprehensive list of specs
if args.recurse_dependencies:
specs_from_user_constraint = specs[:]
@@ -121,7 +164,7 @@ def load_list(mtype, specs, args):
for spec, mod in modules:
d['comment'] = '' if not args.shell else '# {0}\n'.format(spec.format())
d['name'] = mod
- print( prompt_template.format(**d))
+ print(prompt_template.format(**d))
def find(mtype, specs, args):
@@ -143,7 +186,29 @@ def find(mtype, specs, args):
tty.die("No %s module is installed for %s" % (mtype, spec))
print(mod.use_name)
-def refresh(name, specs, args):
+
+def rm(mtype, specs, args):
+ module_cls = module_types[mtype]
+ modules = [module_cls(spec) for spec in specs if os.path.exists(module_cls(spec).file_name)]
+
+ if not modules:
+ tty.msg('No module file matches your query')
+ return
+
+ # Ask for confirmation
+ if not args.yes_to_all:
+ tty.msg('You are about to remove the following module files:\n')
+ for s in modules:
+ print(s.file_name)
+ print('')
+ ask_for_confirmation('Do you want to proceed ? ')
+
+ # Remove the module files
+ for s in modules:
+ s.remove()
+
+
+def refresh(mtype, specs, args):
"""
Regenerate all module files for installed packages known to
spack (some packages may no longer exist).
@@ -153,13 +218,14 @@ def refresh(name, specs, args):
tty.msg('No package matches your query')
return
- tty.msg('You are about to regenerate the {name} module files for the following specs:\n'.format(name=name))
- for s in specs:
- print(s.format(color=True))
- print('')
- ask_for_confirmation('Do you want to proceed ? ')
+ if not args.yes_to_all:
+ tty.msg('You are about to regenerate the {name} module files for the following specs:\n'.format(name=mtype))
+ for s in specs:
+ print(s.format(color=True))
+ print('')
+ ask_for_confirmation('Do you want to proceed ? ')
- cls = module_types[name]
+ cls = module_types[mtype]
# Detect name clashes
writers = [cls(spec) for spec in specs]
@@ -179,48 +245,31 @@ def refresh(name, specs, args):
raise SystemExit(1)
# Proceed regenerating module files
- tty.msg('Regenerating {name} module files'.format(name=name))
+ tty.msg('Regenerating {name} module files'.format(name=mtype))
if os.path.isdir(cls.path) and args.delete_tree:
shutil.rmtree(cls.path, ignore_errors=False)
mkdirp(cls.path)
for x in writers:
x.write(overwrite=True)
-# Qualifiers to be used when querying the db for specs
-constraint_qualifiers = {
- 'refresh': {
- 'installed': True,
- 'known': True
- },
- 'find': {
- },
- 'load-list':{
- }
-}
-
-# Dictionary of callbacks based on the value of module_command
+# Dictionary of callbacks based on the value of subparser_name
callbacks = {
'refresh': refresh,
'find': find,
- 'load-list': load_list
+ 'load-list': load_list,
+ 'rm': rm
}
def module(parser, args):
module_type = args.module_type
- # Query specs from command line
- qualifiers = constraint_qualifiers[args.module_command]
- specs = [s for s in spack.installed_db.query(**qualifiers)]
- constraint = ' '.join(args.constraint)
- if constraint:
- specs = [x for x in specs if x.satisfies(constraint, strict=True)]
- # Call the appropriate function
+ constraint = args.constraint
try:
- callbacks[args.module_command](module_type, specs, args)
+ callbacks[args.subparser_name](module_type, args.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:
+ for s in args.specs:
sys.stderr.write(s.format(color=True) + '\n')
raise SystemExit(1)
except NoMatch: