diff --git a/lib/spack/spack/modules/common.py b/lib/spack/spack/modules/common.py index 2ce05a818f4..702d473c556 100644 --- a/lib/spack/spack/modules/common.py +++ b/lib/spack/spack/modules/common.py @@ -330,18 +330,17 @@ class BaseConfiguration: default_projections = {"all": "{name}/{version}-{compiler.name}-{compiler.version}"} def __init__(self, spec: spack.spec.Spec, module_set_name: str, explicit: bool) -> None: - # Module where type(self) is defined - m = inspect.getmodule(self) - assert m is not None # make mypy happy - self.module = m # Spec for which we want to generate a module file self.spec = spec self.name = module_set_name self.explicit = explicit - # Dictionary of configuration options that should be applied - # to the spec + # Dictionary of configuration options that should be applied to the spec self.conf = merge_config_rules(self.module.configuration(self.name), self.spec) + @property + def module(self): + return inspect.getmodule(self) + @property def projections(self): """Projection from specs to module names""" @@ -775,10 +774,6 @@ def __init__( ) -> None: self.spec = spec - # This class is meant to be derived. Get the module of the - # actual writer. - self.module = inspect.getmodule(self) - assert self.module is not None # make mypy happy m = self.module # Create the triplet of configuration/layout/context @@ -816,6 +811,10 @@ def __init__( name = type(self).__name__ raise ModulercHeaderNotDefined(msg.format(name)) + @property + def module(self): + return inspect.getmodule(self) + def _get_template(self): """Gets the template that will be rendered for this spec.""" # Get templates and put them in the order of importance: diff --git a/lib/spack/spack/test/modules/common.py b/lib/spack/spack/test/modules/common.py index 76f64a22f52..0d858806e5d 100644 --- a/lib/spack/spack/test/modules/common.py +++ b/lib/spack/spack/test/modules/common.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) import os +import pickle import stat import pytest @@ -223,3 +224,10 @@ def test_check_module_set_name(mutable_config): with pytest.raises(spack.error.ConfigError, match=msg): spack.cmd.modules.check_module_set_name("third") + + +@pytest.mark.parametrize("module_type", ["tcl", "lmod"]) +def test_module_writers_are_pickleable(default_mock_concretization, module_type): + s = default_mock_concretization("mpileaks") + writer = spack.modules.module_types[module_type](s, "default") + assert pickle.loads(pickle.dumps(writer)).spec == s