module : added rm subcommand, encapsulated logic for constraints in argarse.Action subclass

This commit is contained in:
alalazo 2016-07-01 14:27:55 +02:00
parent fe4ef286f2
commit f0f7b23c8a

View File

@ -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))
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: