modules: restore exclude_implicits (#40958)

This commit is contained in:
Harmen Stoppels 2023-11-08 22:56:55 +01:00 committed by Harmen Stoppels
parent fc5fd7fc60
commit 9d58d5e645
4 changed files with 19 additions and 99 deletions

View file

@ -486,43 +486,35 @@ def excluded(self):
spec = self.spec spec = self.spec
conf = self.module.configuration(self.name) conf = self.module.configuration(self.name)
# Compute the list of include rules that match # Compute the list of matching include / exclude rules, and whether excluded as implicit
include_rules = conf.get("include", []) include_matches = [x for x in conf.get("include", []) if spec.satisfies(x)]
include_matches = [x for x in include_rules if spec.satisfies(x)] exclude_matches = [x for x in conf.get("exclude", []) if spec.satisfies(x)]
excluded_as_implicit = not self.explicit and conf.get("exclude_implicits", False)
# Compute the list of exclude rules that match
exclude_rules = conf.get("exclude", [])
exclude_matches = [x for x in exclude_rules if spec.satisfies(x)]
def debug_info(line_header, match_list): def debug_info(line_header, match_list):
if match_list: if match_list:
msg = "\t{0} : {1}".format(line_header, spec.cshort_spec) tty.debug(f"\t{line_header} : {spec.cshort_spec}")
tty.debug(msg)
for rule in match_list: for rule in match_list:
tty.debug("\t\tmatches rule: {0}".format(rule)) tty.debug(f"\t\tmatches rule: {rule}")
debug_info("INCLUDE", include_matches) debug_info("INCLUDE", include_matches)
debug_info("EXCLUDE", exclude_matches) debug_info("EXCLUDE", exclude_matches)
if not include_matches and exclude_matches: if excluded_as_implicit:
return True tty.debug(f"\tEXCLUDED_AS_IMPLICIT : {spec.cshort_spec}")
return False return not include_matches and (exclude_matches or excluded_as_implicit)
@property @property
def hidden(self): def hidden(self):
"""Returns True if the module has been hidden, False otherwise.""" """Returns True if the module has been hidden, False otherwise."""
# A few variables for convenience of writing the method
spec = self.spec
conf = self.module.configuration(self.name) conf = self.module.configuration(self.name)
hidden_as_implicit = not self.explicit and conf.get( hidden_as_implicit = not self.explicit and conf.get("hide_implicits", False)
"hide_implicits", conf.get("exclude_implicits", False)
)
if hidden_as_implicit: if hidden_as_implicit:
tty.debug(f"\tHIDDEN_AS_IMPLICIT : {spec.cshort_spec}") tty.debug(f"\tHIDDEN_AS_IMPLICIT : {self.spec.cshort_spec}")
return hidden_as_implicit return hidden_as_implicit

View file

@ -188,52 +188,3 @@
"additionalProperties": False, "additionalProperties": False,
"properties": properties, "properties": properties,
} }
# deprecated keys and their replacements
old_to_new_key = {"exclude_implicits": "hide_implicits"}
def update_keys(data, key_translations):
"""Change blacklist/whitelist to exclude/include.
Arguments:
data (dict): data from a valid modules configuration.
key_translations (dict): A dictionary of keys to translate to
their respective values.
Return:
(bool) whether anything was changed in data
"""
changed = False
if isinstance(data, dict):
keys = list(data.keys())
for key in keys:
value = data[key]
translation = key_translations.get(key)
if translation:
data[translation] = data.pop(key)
changed = True
changed |= update_keys(value, key_translations)
elif isinstance(data, list):
for elt in data:
changed |= update_keys(elt, key_translations)
return changed
def update(data):
"""Update the data in place to remove deprecated properties.
Args:
data (dict): dictionary to be updated
Returns:
True if data was changed, False otherwise
"""
# translate blacklist/whitelist to exclude/include
return update_keys(data, old_to_new_key)

View file

@ -14,7 +14,6 @@
import spack.package_base import spack.package_base
import spack.schema.modules import spack.schema.modules
import spack.spec import spack.spec
import spack.util.spack_yaml as syaml
from spack.modules.common import UpstreamModuleIndex from spack.modules.common import UpstreamModuleIndex
from spack.spec import Spec from spack.spec import Spec
@ -191,26 +190,6 @@ def find_nothing(*args):
spack.package_base.PackageBase.uninstall_by_spec(spec) spack.package_base.PackageBase.uninstall_by_spec(spec)
@pytest.mark.parametrize(
"module_type, old_config,new_config",
[("tcl", "exclude_implicits.yaml", "hide_implicits.yaml")],
)
def test_exclude_include_update(module_type, old_config, new_config):
module_test_data_root = os.path.join(spack.paths.test_path, "data", "modules", module_type)
with open(os.path.join(module_test_data_root, old_config)) as f:
old_yaml = syaml.load(f)
with open(os.path.join(module_test_data_root, new_config)) as f:
new_yaml = syaml.load(f)
# ensure file that needs updating is translated to the right thing.
assert spack.schema.modules.update_keys(old_yaml, spack.schema.modules.old_to_new_key)
assert new_yaml == old_yaml
# ensure a file that doesn't need updates doesn't get updated
original_new_yaml = new_yaml.copy()
assert not spack.schema.modules.update_keys(new_yaml, spack.schema.modules.old_to_new_key)
assert original_new_yaml == new_yaml
@pytest.mark.regression("37649") @pytest.mark.regression("37649")
def test_check_module_set_name(mutable_config): def test_check_module_set_name(mutable_config):
"""Tests that modules set name are validated correctly and an error is reported if the """Tests that modules set name are validated correctly and an error is reported if the

View file

@ -425,40 +425,38 @@ def test_extend_context(self, modulefile_content, module_configuration):
@pytest.mark.regression("4400") @pytest.mark.regression("4400")
@pytest.mark.db @pytest.mark.db
@pytest.mark.parametrize("config_name", ["hide_implicits", "exclude_implicits"]) def test_hide_implicits_no_arg(self, module_configuration, database):
def test_hide_implicits_no_arg(self, module_configuration, database, config_name): module_configuration("exclude_implicits")
module_configuration(config_name)
# mpileaks has been installed explicitly when setting up # mpileaks has been installed explicitly when setting up
# the tests database # the tests database
mpileaks_specs = database.query("mpileaks") mpileaks_specs = database.query("mpileaks")
for item in mpileaks_specs: for item in mpileaks_specs:
writer = writer_cls(item, "default") writer = writer_cls(item, "default")
assert not writer.conf.hidden assert not writer.conf.excluded
# callpath is a dependency of mpileaks, and has been pulled # callpath is a dependency of mpileaks, and has been pulled
# in implicitly # in implicitly
callpath_specs = database.query("callpath") callpath_specs = database.query("callpath")
for item in callpath_specs: for item in callpath_specs:
writer = writer_cls(item, "default") writer = writer_cls(item, "default")
assert writer.conf.hidden assert writer.conf.excluded
@pytest.mark.regression("12105") @pytest.mark.regression("12105")
@pytest.mark.parametrize("config_name", ["hide_implicits", "exclude_implicits"]) def test_hide_implicits_with_arg(self, module_configuration):
def test_hide_implicits_with_arg(self, module_configuration, config_name): module_configuration("exclude_implicits")
module_configuration(config_name)
# mpileaks is defined as explicit with explicit argument set on writer # mpileaks is defined as explicit with explicit argument set on writer
mpileaks_spec = spack.spec.Spec("mpileaks") mpileaks_spec = spack.spec.Spec("mpileaks")
mpileaks_spec.concretize() mpileaks_spec.concretize()
writer = writer_cls(mpileaks_spec, "default", True) writer = writer_cls(mpileaks_spec, "default", True)
assert not writer.conf.hidden assert not writer.conf.excluded
# callpath is defined as implicit with explicit argument set on writer # callpath is defined as implicit with explicit argument set on writer
callpath_spec = spack.spec.Spec("callpath") callpath_spec = spack.spec.Spec("callpath")
callpath_spec.concretize() callpath_spec.concretize()
writer = writer_cls(callpath_spec, "default", False) writer = writer_cls(callpath_spec, "default", False)
assert writer.conf.hidden assert writer.conf.excluded
@pytest.mark.regression("9624") @pytest.mark.regression("9624")
@pytest.mark.db @pytest.mark.db