Modulefiles generated with a template engine#3183
Conversation
58882bc to
1b48cdd
Compare
|
This is awesome! Some things to consider:
At ANL's LCRC, we are getting ready to make the switch from our own homegrown SoftEnv package to Lmod. I started playing around with Spack's Lmod support and found a few problems worth fixing. I was going to try to take a stab at some of these, but will obviously wait until this PR is done now. You're welcome to try to solve some of these if you like:
|
|
Hey @adamjstewart thanks for the quick feedback! Before I start a by-point reply: feel free to post any problem you encounter with modules (or open an issue an point me to that 😄 ). I'll try to fix what I can here. About this PR
I am willing to merge their functionality here (or let the original author of the PR do that if they prefer). For #2902 this is basically done, as templates are designed to be extended. I still need to check what #2345 does (thanks for the ping yesterday). Others?
That would simplify life! I would like to hear what @tgamblin thinks about it. Currently I used only basic features in templates (i.e. the ones that would have permitted to write a replacement for About
|
|
Sounds good to me. I did a quick run-through of all open Issues and PRs and labeled any that I thought were related to modules: |
|
|
First of all thanks a lot for the great work on modules. Using template for module generation was something I had in mind since a while and now here it is ;-)
|
|
Also, we would need to get #2664 merged before this PR messes with |
|
@citibeth I don't plan to touch commands here. |
7e15211 to
08b9f16
Compare
The mechanism currently implemented permits you to specify a list of config:
# Locations where templates should be found
template_dirs:
- $spack/templatesTo override templates for module files you have then two possibilities. The first one is at package level, if it makes sense to do so. In this case you need to set e.g. the The second possibility (with higher precedence) is to specify the template in the
You can use all the powers of jinja2 and the mechanisms above to define custom code for your templates.
It's always ok to submit a PR. Maybe you want to ask people in #2924 for an update on the state of things. Do you think that work will be related to this refactoring?
Start using lmod! 😄 |
39db11f to
a4e5104
Compare
|
@TheQueasle I think you may be interested in this PR as it should extend the functionality introduced in #2902 . Can you tell me if it fits your use case? |
|
@alalazo Cursory glance things look good. I'll need to carve out some time to play around with this to be 100% sure. Honestly though, so long as I can inject arbitrary code in the generated modulefiles it will suit me just fine, and it looks like you covered that usecase already. 😄 |
d7aa049 to
ceaac9c
Compare
|
@adamjstewart The latest commit should address the change in behavior for |
| choices=spack.modules.module_types.keys(), | ||
| default=spack.modules.module_types.keys()[0], | ||
| action='append', | ||
| help='type of module files [default: %(default)s]') |
There was a problem hiding this comment.
What's your plan with the default? Also, if you change the default, make sure to change the help message.
There was a problem hiding this comment.
Good catch on the help message. I changed the action to append so that one can do:
spack module refresh -m tcl -m lmod ...
The default is the one you proposed (all the module files that are known) except that it's set in the method module.
3be6ab0 to
89498e4
Compare
|
@tgamblin @adamjstewart @becker33 @scheibelp and anybody interested: I think this PR is ready for a first review round. I'll be waiting for questions / comments. |
63b0ca3 to
0d113fd
Compare
19fed1f to
07ae702
Compare
The correct place to set the mutual references between spec and package objects at the end of concretization. After a call to concretize we should now be ensured that spec is the same object as spec.package.spec. Code in `build_environment.py` that was performing the same operation has been turned into an assertion to be defensive on the new behavior.
spack#3173 jinja2 has been hooked into Spack. The python module `modules.py` has been splitted into several modules under the python package `spack/modules`. Unit tests stressing module file generation have been refactored accordingly. The module file generator for Lmod has been extended to multi-providers and deeper hierarchies.
Added an entry in `config.yaml` (`template_dirs`) to list all the
directories where Spack could find templates for `jinja2`.
Module file generators have a simple override mechanism to override
template selection ('modules.yaml' beats 'package.py' beats 'default').
Common fixtures related to module file generation have been extracted in `conftest.py`. All the mock configurations for module files have been extracted from python code and have been put into their own yaml file. Added a `context_property` decorator for the template engine, to make it easy to define dictionaries out of properties. The default for `verbose` in `modules.yaml` is now False instead of True.
The contexts that are used in conjunction with `jinja2` templates to generate module files can now be extended from package.py and modules.yaml. Module files generators now infer the short description from package.py docstring (and as you may expect it's the first paragraph)
`module refresh` without `--module-type` specified tries to regenerate all known module types. The same holds true for `module rm` Configure options used at build time are extracted and written into the module files where possible.
Added test for exceptional paths of execution when generating Lmod module files. Fixed a few compatibility issues with python3. Fixed a bug in Tcl with naming_scheme and autoload + unit tests
The reference section for module files has been reorganized. The idea is to have only three topics at the highest level: - shell support + spack load/unload use/unuse - module file generation (a.k.a. APIs + modules.yaml) - module file maintenance (spack module refresh/rm) Module file generation will cover the entries in modules.yaml Also: - Licenses have been updated to include NOTICE and extended to 2017 - docstrings have been reformatted according to Google style
All the callbacks in `RPackage` and `WafPackage` that are not build phases have been modified not to accept a `spec` and a `prefix` argument. This permits to leverage the common `configure_args` signature to insert by default the configuration arguments into the generated module files. I think it's preferable to handling those packages differently than `AutotoolsPackage`. Besides only one package seems to override one of these methods.
Fixed broken indentation in `spack module refresh` (probably a rebase gone silently wrong?). Filter the writers for blacklisted specs before searching for name clashes. An error with a single writer will not stop regeneration, but instead will print a warning and continue the command.
07ae702 to
38bc977
Compare
spack#3183 removed the print_help function from the "modules" module. This adds it back so that if a user invokes 'spack load foo' without having sourced an environment setup script, they will be prompted to do so.
spack#3183 removed the print_help function from the "modules" module. This adds it back so that if a user invokes 'spack load foo' without having sourced an environment setup script, they will be prompted to do so.
spack#3183 removed the print_help function from the "modules" module. This adds it back so that if a user invokes 'spack load foo' without having sourced an environment setup script, they will be prompted to do so.
Fixes #6126 #3183 removed the print_help function from the "modules" module. This adds it back so that if a user invokes 'spack load foo' without having sourced an environment setup script, they will be prompted to do so. This also improves the placeholder message to tell the user to invoke 'spack' as shell function rather than as an executable.
TLDR
This PR is a big refactoring effort on module files (with only little changes on the UI side) that introduces the use of template engines in
spack. Iit relies onjinja2that will be shipped as an external, at least until we solve #1385. I also plan to add a lot more tests on hierarchical module files generation.Motivation
I started the PR because I needed to extend lmod module file generation to take into account packages that provide more than one service (hello
intel-parallel-studio!) and figured out that this part of the code has grown enough in size and complexity to benefit from using a template engine for generation.I also think that this capability may be reused in many places like:
spack createcommandspack loadsandspack setupcommandsi.e. basically everywhere we need to generate a file with a clear structure starting from the information in a DAG or in the DB.
Modifications planned (or already done)
Template engine in spack
template_dirsinconfig.yamlto list the directories we should search for templates.externalModulefiles
spack/modules).spack module refreshpermits to generate every module file known, not just the enabled ones).spack module refreshwithout any specific--module-typerefreshes all enabled module types.AutotoolsPackageandCMakePackageobjects.spec.formatthat can be used in the naming scheme (see Module naming schemeOPTIONSand theemacspackage #2884)Changes in UI
autoload_verboseto justverboseand made it default toFalse. Its location is at the same level aswhitelistsandblacklists.