module : added rm subcommand, encapsulated logic for constraints in argarse.Action subclass
This commit is contained in:
parent
fe4ef286f2
commit
f0f7b23c8a
@ -28,6 +28,7 @@
|
||||
import shutil
|
||||
import sys
|
||||
import collections
|
||||
import argparse
|
||||
|
||||
import llnl.util.tty as tty
|
||||
import spack.cmd
|
||||
@ -40,33 +41,76 @@
|
||||
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))
|
||||
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:
|
||||
|
Loading…
Reference in New Issue
Block a user