From 22bec329c1824ecd3271fffcef9ff793363ba93d Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Sat, 16 Aug 2014 22:22:34 -0700 Subject: [PATCH] Bugfixes, more consolidation of modules code. - specific module classes use __metaclass__ to register themselves. - bugfixes in module writing. --- .gitignore | 1 + lib/spack/spack/cmd/module.py | 25 +++++++++++++------------ lib/spack/spack/modules.py | 35 ++++++++++++++++++++++++++--------- lib/spack/spack/packages.py | 10 ++++++++++ 4 files changed, 50 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index d6e0d3e60c..828fb04e7d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ .idea /etc/spackconfig /share/spack/dotkit +/share/spack/modules diff --git a/lib/spack/spack/cmd/module.py b/lib/spack/spack/cmd/module.py index ead3b9abac..af5a68923b 100644 --- a/lib/spack/spack/cmd/module.py +++ b/lib/spack/spack/cmd/module.py @@ -32,18 +32,13 @@ from llnl.util.filesystem import mkdirp import spack.cmd -import spack.modules +from spack.modules import module_types from spack.util.string import * from spack.spec import Spec description ="Manipulate modules and dotkits." -module_types = { - 'dotkit' : spack.modules.Dotkit, - 'tcl' : spack.modules.TclModule -} - def setup_parser(subparser): sp = subparser.add_subparsers(metavar='SUBCOMMAND', dest='module_command') @@ -87,13 +82,19 @@ def module_find(mtype, spec_array): def module_refresh(): - shutil.rmtree(spack.dotkit_path, ignore_errors=False) - mkdirp(spack.dotkit_path) + """Regenerate all module files for installed packages known to + spack (some packages may no longer exist).""" + specs = [s for s in spack.db.installed_known_package_specs()] + + 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: + tty.debug(" Writing file for %s." % spec) + cls(spec.package).write() - specs = spack.db.installed_package_specs() - for spec in specs: - for mt in module_types: - mt(spec.package).write() def module(parser, args): diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py index 0f8c417793..596308f801 100644 --- a/lib/spack/spack/modules.py +++ b/lib/spack/spack/modules.py @@ -56,8 +56,10 @@ import spack -dotkit_path = join_path(spack.share_path, "dotkit") -tcl_mod_path = join_path(spack.share_path, "modules") +"""Registry of all types of modules. Entries created by EnvModule's + metaclass.""" +module_types = {} + def print_help(): """For use by commands to tell user how to activate shell support.""" @@ -77,6 +79,15 @@ def print_help(): class EnvModule(object): + name = 'env_module' + + class __metaclass__(type): + def __init__(cls, name, bases, dict): + type.__init__(cls, name, bases, dict) + if cls.name != 'env_module': + module_types[cls.name] = cls + + def __init__(self, pkg=None): # category in the modules system # TODO: come up with smarter category names. @@ -97,7 +108,7 @@ def paths(self): if self._paths is None: self._paths = {} - def add_path(self, path_name, directory): + def add_path(path_name, directory): path = self._paths.setdefault(path_name, []) path.append(directory) @@ -126,14 +137,14 @@ def add_path(self, path_name, directory): def write(self): """Write out a module file for this object.""" module_dir = os.path.dirname(self.file_name) - if not os.path.exists(): + if not os.path.exists(module_dir): mkdirp(module_dir) # If there are no paths, no need for a dotkit. if not self.paths: return - with closing(open(self.file_name)) as f: + with closing(open(self.file_name, 'w')) as f: self._write(f) @@ -156,10 +167,13 @@ def remove(self): class Dotkit(EnvModule): + name = 'dotkit' + path = join_path(spack.share_path, "dotkit") + @property def file_name(self): spec = self.pkg.spec - return join_path(dotkit_path, spec.architecture, + return join_path(Dotkit.path, spec.architecture, spec.format('$_$@$%@$+$#.dk')) @@ -183,14 +197,17 @@ def _write(self, dk_file): dk_file.write("dk_alter %s %s\n" % (var, directory)) # Let CMake find this package. - dk_file.write("dk_alter CMAKE_PREFIX_PATH %s\n" % pkg.prefix) + dk_file.write("dk_alter CMAKE_PREFIX_PATH %s\n" % self.pkg.prefix) class TclModule(EnvModule): + name = 'tcl' + path = join_path(spack.share_path, "modules") + @property def file_name(self): spec = self.pkg.spec - return join_path(tcl_mod_path, spec.architecture, + return join_path(TclModule.path, spec.architecture, spec.format('$_$@$%@$+$#')) @@ -214,4 +231,4 @@ def _write(self, m_file): for directory in dirs: m_file.write("prepend-path %s \"%s\"\n" % (var, directory)) - m_file.write("prepend-path CMAKE_PREFIX_PATH \"%s\"\n" % pkg.prefix) + m_file.write("prepend-path CMAKE_PREFIX_PATH \"%s\"\n" % self.pkg.prefix) diff --git a/lib/spack/spack/packages.py b/lib/spack/spack/packages.py index 00834c95d5..f9840a5c05 100644 --- a/lib/spack/spack/packages.py +++ b/lib/spack/spack/packages.py @@ -118,6 +118,16 @@ def installed_package_specs(self): return spack.install_layout.all_specs() + def installed_known_package_specs(self): + """Read installed package names straight from the install + directory layout, but return only specs for which the + package is known to this version of spack. + """ + for spec in spack.install_layout.all_specs(): + if self.exists(spec.name): + yield spec + + @memoized def all_package_names(self): """Generator function for all packages. This looks for