summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authoralalazo <massimiliano.culpo@googlemail.com>2016-06-28 17:59:34 +0200
committeralalazo <massimiliano.culpo@googlemail.com>2016-06-28 19:28:18 +0200
commitb71d430af6025cb46ac574e91e516bc5c4caf048 (patch)
tree19a7b5c73b7c2406df46190d7efd1143c79123c1 /lib
parent0fd58fb5857f7ff1f10b76622c7cd3823e68f813 (diff)
downloadspack-b71d430af6025cb46ac574e91e516bc5c4caf048.tar.gz
spack-b71d430af6025cb46ac574e91e516bc5c4caf048.tar.bz2
spack-b71d430af6025cb46ac574e91e516bc5c4caf048.tar.xz
spack-b71d430af6025cb46ac574e91e516bc5c4caf048.zip
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
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/cmd/module.py140
-rw-r--r--lib/spack/spack/modules.py8
2 files changed, 95 insertions, 53 deletions
diff --git a/lib/spack/spack/cmd/module.py b/lib/spack/spack/cmd/module.py
index 5292d42225..c71e615d1c 100644
--- a/lib/spack/spack/cmd/module.py
+++ b/lib/spack/spack/cmd/module.py
@@ -32,73 +32,115 @@ from llnl.util.filesystem import mkdirp
from spack.modules import module_types
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):
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.add_argument('module_type',
- 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):
- """Look at all installed packages and see if the spec provided
- matches any. If it does, check whether there is a module file
- of type <mtype> there, and print out the name that the user
- 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)))
+ _add_common_arguments(find_parser)
- 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)
+class MultipleMatches(Exception):
+ 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
+ of type <mtype> there, and print out the name that the user
+ should type to use that package's module.
+ """
if len(specs) == 0:
- tty.die("No installed packages match spec %s" % spec)
+ raise NoMatch()
if len(specs) > 1:
- tty.error("Multiple matches for spec %s. Choose one:" % spec)
- for s in specs:
- sys.stderr.write(s.tree(color=True))
- sys.exit(1)
+ raise MultipleMatches()
- mt = module_types[mtype]
- mod = mt(specs[0])
+ mod = module_types[mtype](specs.pop())
if not os.path.isfile(mod.file_name):
tty.die("No %s module is installed for %s" % (mtype, spec))
print(mod.use_name)
-def module_refresh():
- """Regenerate all module files for installed packages known to
- spack (some packages may no longer exist)."""
- specs = [s for s in spack.installed_db.query(installed=True, known=True)]
-
- for name, cls in module_types.items():
- tty.msg("Regenerating %s module files." % name)
- if os.path.isdir(cls.path):
- shutil.rmtree(cls.path, ignore_errors=False)
- mkdirp(cls.path)
- for spec in specs:
- cls(spec).write()
+def module_refresh(name, specs, args):
+ """
+ Regenerate all module files for installed packages known to
+ 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
+
+ tty.msg('You are about to regenerate the {name} module files for the following specs:'.format(name=name))
+ for s in specs:
+ 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)
+ mkdirp(cls.path)
+ for spec in specs:
+ 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):
- if args.module_command == 'refresh':
- module_refresh()
-
- elif args.module_command == 'find':
- module_find(args.module_type, args.spec)
+ 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
+ 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))
diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py
index ce46047fa3..068179c0ce 100644
--- a/lib/spack/spack/modules.py
+++ b/lib/spack/spack/modules.py
@@ -454,7 +454,7 @@ class EnvModule(object):
class Dotkit(EnvModule):
name = 'dotkit'
-
+ path = join_path(spack.share_path, 'dotkit')
environment_modifications_formats = {
PrependPath: 'dk_alter {name} {value}\n',
SetEnv: 'dk_setenv {name} {value}\n'
@@ -466,7 +466,7 @@ class Dotkit(EnvModule):
@property
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)
@property
@@ -494,7 +494,7 @@ class Dotkit(EnvModule):
class TclModule(EnvModule):
name = 'tcl'
-
+ path = join_path(spack.share_path, "modules")
environment_modifications_formats = {
PrependPath: 'prepend-path --delim "{delim}" {name} \"{value}\"\n',
AppendPath: 'append-path --delim "{delim}" {name} \"{value}\"\n',
@@ -514,7 +514,7 @@ class TclModule(EnvModule):
@property
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
def header(self):