modules: allow autoload: run, like in environment views (#42743)

This commit is contained in:
Harmen Stoppels 2024-03-04 08:49:45 +01:00 committed by GitHub
parent d1fa23e9c6
commit 5d994e48d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 34 deletions

View file

@ -273,9 +273,21 @@ builtin support through the ``depends_on`` function, the latter simply uses a ``
statement. Both module systems (at least in newer versions) do reference counting, so that if a statement. Both module systems (at least in newer versions) do reference counting, so that if a
module is loaded by two different modules, it will only be unloaded after the others are. module is loaded by two different modules, it will only be unloaded after the others are.
The ``autoload`` key accepts the values ``none``, ``direct``, and ``all``. To disable it, use The ``autoload`` key accepts the values:
``none``, and to enable, it's best to stick to ``direct``, which only autoloads the direct link and
run type dependencies, relying on recursive autoloading to load the rest. * ``none``: no autoloading
* ``run``: autoload direct *run* type dependencies
* ``direct``: autoload direct *link and run* type dependencies
* ``all``: autoload all dependencies
In case of ``run`` and ``direct``, a ``module load`` triggers a recursive load.
The ``direct`` option is most correct: there are cases where pure link dependencies need to set
variables for themselves, or need to have variables of their own dependencies set.
In practice however, ``run`` is often sufficient, and may make ``module load`` snappier.
The ``all`` option is discouraged and seldomly used.
A common complaint about autoloading is the large number of modules that are visible to the user. A common complaint about autoloading is the large number of modules that are visible to the user.
Spack has a solution for this as well: ``hide_implicits: true``. This ensures that only those Spack has a solution for this as well: ``hide_implicits: true``. This ensures that only those
@ -297,11 +309,11 @@ Environment Modules requires version 4.7 or higher.
tcl: tcl:
hide_implicits: true hide_implicits: true
all: all:
autoload: direct autoload: direct # or `run`
lmod: lmod:
hide_implicits: true hide_implicits: true
all: all:
autoload: direct autoload: direct # or `run`
.. _anonymous_specs: .. _anonymous_specs:

View file

@ -121,43 +121,26 @@ def update_dictionary_extending_lists(target, update):
target[key] = update[key] target[key] = update[key]
def dependencies(spec, request="all"): def dependencies(spec: spack.spec.Spec, request: str = "all") -> List[spack.spec.Spec]:
"""Returns the list of dependent specs for a given spec, according to the """Returns the list of dependent specs for a given spec.
request passed as parameter.
Args: Args:
spec: spec to be analyzed spec: spec to be analyzed
request: either 'none', 'direct' or 'all' request: one of "none", "run", "direct", "all"
Returns: Returns:
list of dependencies list of requested dependencies
The return list will be empty if request is 'none', will contain
the direct dependencies if request is 'direct', or the entire DAG
if request is 'all'.
""" """
if request not in ("none", "direct", "all"):
message = "Wrong value for argument 'request' : "
message += "should be one of ('none', 'direct', 'all')"
raise tty.error(message + " [current value is '%s']" % request)
if request == "none": if request == "none":
return [] return []
elif request == "run":
return spec.dependencies(deptype=dt.RUN)
elif request == "direct":
return spec.dependencies(deptype=dt.RUN | dt.LINK)
elif request == "all":
return list(spec.traverse(order="topo", deptype=dt.LINK | dt.RUN, root=False))
if request == "direct": raise ValueError(f'request "{request}" is not one of "none", "direct", "run", "all"')
return spec.dependencies(deptype=("link", "run"))
# FIXME : during module file creation nodes seem to be visited multiple
# FIXME : times even if cover='nodes' is given. This work around permits
# FIXME : to get a unique list of spec anyhow. Do we miss a merge
# FIXME : step among nodes that refer to the same package?
seen = set()
seen_add = seen.add
deps = sorted(
spec.traverse(order="post", cover="nodes", deptype=("link", "run"), root=False),
reverse=True,
)
return [d for d in deps if not (d in seen or seen_add(d))]
def merge_config_rules(configuration, spec): def merge_config_rules(configuration, spec):

View file

@ -34,7 +34,7 @@
dictionary_of_strings = {"type": "object", "patternProperties": {r"\w[\w-]*": {"type": "string"}}} dictionary_of_strings = {"type": "object", "patternProperties": {r"\w[\w-]*": {"type": "string"}}}
dependency_selection = {"type": "string", "enum": ["none", "direct", "all"]} dependency_selection = {"type": "string", "enum": ["none", "run", "direct", "all"]}
module_file_configuration = { module_file_configuration = {
"type": "object", "type": "object",