environment.py: fix excessive re-reads (#43746)

This commit is contained in:
Harmen Stoppels 2024-04-19 21:39:34 +02:00 committed by GitHub
parent 39888d4df6
commit 44cb4eca93
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 33 additions and 28 deletions

View file

@ -1562,8 +1562,9 @@ def ensure_latest_format_fn(section: str) -> Callable[[YamlConfigDict], bool]:
def use_configuration( def use_configuration(
*scopes_or_paths: Union[ConfigScope, str] *scopes_or_paths: Union[ConfigScope, str]
) -> Generator[Configuration, None, None]: ) -> Generator[Configuration, None, None]:
"""Use the configuration scopes passed as arguments within the """Use the configuration scopes passed as arguments within the context manager.
context manager.
This function invalidates caches, and is therefore very slow.
Args: Args:
*scopes_or_paths: scope objects or paths to be used *scopes_or_paths: scope objects or paths to be used

View file

@ -106,17 +106,16 @@ def environment_name(path: Union[str, pathlib.Path]) -> str:
return path_str return path_str
def check_disallowed_env_config_mods(scopes): def ensure_no_disallowed_env_config_mods(scopes: List[spack.config.ConfigScope]) -> None:
for scope in scopes: for scope in scopes:
with spack.config.use_configuration(scope): config = scope.get_section("config")
if spack.config.get("config:environments_root"): if config and "environments_root" in config["config"]:
raise SpackEnvironmentError( raise SpackEnvironmentError(
"Spack environments are prohibited from modifying 'config:environments_root' " "Spack environments are prohibited from modifying 'config:environments_root' "
"because it can make the definition of the environment ill-posed. Please " "because it can make the definition of the environment ill-posed. Please "
"remove from your environment and place it in a permanent scope such as " "remove from your environment and place it in a permanent scope such as "
"defaults, system, site, etc." "defaults, system, site, etc."
) )
return scopes
def default_manifest_yaml(): def default_manifest_yaml():
@ -2463,6 +2462,10 @@ def __init__(self, manifest_dir: Union[pathlib.Path, str]) -> None:
self.scope_name = f"env:{environment_name(self.manifest_dir)}" self.scope_name = f"env:{environment_name(self.manifest_dir)}"
self.config_stage_dir = os.path.join(env_subdir_path(manifest_dir), "config") self.config_stage_dir = os.path.join(env_subdir_path(manifest_dir), "config")
#: Configuration scopes associated with this environment. Note that these are not
#: invalidated by a re-read of the manifest file.
self._config_scopes: Optional[List[spack.config.ConfigScope]] = None
if not self.manifest_file.exists(): if not self.manifest_file.exists():
msg = f"cannot find '{manifest_name}' in {self.manifest_dir}" msg = f"cannot find '{manifest_name}' in {self.manifest_dir}"
raise SpackEnvironmentError(msg) raise SpackEnvironmentError(msg)
@ -2808,16 +2811,19 @@ def included_config_scopes(self) -> List[spack.config.ConfigScope]:
@property @property
def env_config_scopes(self) -> List[spack.config.ConfigScope]: def env_config_scopes(self) -> List[spack.config.ConfigScope]:
"""A list of all configuration scopes for the environment manifest. """A list of all configuration scopes for the environment manifest. On the first call this
instantiates all the scopes, on subsequent calls it returns the cached list."""
Returns: All configuration scopes associated with the environment if self._config_scopes is not None:
""" return self._config_scopes
config_name = self.scope_name scopes: List[spack.config.ConfigScope] = [
env_scope = spack.config.SingleFileScope( *self.included_config_scopes,
config_name, str(self.manifest_file), spack.schema.env.schema, [TOP_LEVEL_KEY] spack.config.SingleFileScope(
) self.scope_name, str(self.manifest_file), spack.schema.env.schema, [TOP_LEVEL_KEY]
),
return check_disallowed_env_config_mods(self.included_config_scopes + [env_scope]) ]
ensure_no_disallowed_env_config_mods(scopes)
self._config_scopes = scopes
return scopes
def prepare_config_scope(self) -> None: def prepare_config_scope(self) -> None:
"""Add the manifest's scopes to the global configuration search path.""" """Add the manifest's scopes to the global configuration search path."""

View file

@ -858,8 +858,7 @@ def test_with_config_bad_include_activate(environment_from_manifest, tmpdir):
""" """
) )
e = ev.Environment(env_root) with ev.Environment(env_root) as e:
with e:
e.concretize() e.concretize()
# we've created an environment with some included config files (which do # we've created an environment with some included config files (which do
@ -869,7 +868,7 @@ def test_with_config_bad_include_activate(environment_from_manifest, tmpdir):
os.remove(abs_include_path) os.remove(abs_include_path)
os.remove(include1) os.remove(include1)
with pytest.raises(spack.config.ConfigFileError) as exc: with pytest.raises(spack.config.ConfigFileError) as exc:
ev.activate(e) ev.activate(ev.Environment(env_root))
err = exc.value.message err = exc.value.message
assert "missing include" in err assert "missing include" in err
@ -1063,8 +1062,7 @@ def test_config_change_new(mutable_mock_env_path, tmp_path, mock_packages, mutab
""" """
) )
e = ev.Environment(tmp_path) with ev.Environment(tmp_path):
with e:
config("change", "packages:mpich:require:~debug") config("change", "packages:mpich:require:~debug")
with pytest.raises(spack.solver.asp.UnsatisfiableSpecError): with pytest.raises(spack.solver.asp.UnsatisfiableSpecError):
spack.spec.Spec("mpich+debug").concretized() spack.spec.Spec("mpich+debug").concretized()
@ -1081,7 +1079,7 @@ def test_config_change_new(mutable_mock_env_path, tmp_path, mock_packages, mutab
require: "@3.0.3" require: "@3.0.3"
""" """
) )
with e: with ev.Environment(tmp_path):
assert spack.spec.Spec("mpich").concretized().satisfies("@3.0.3") assert spack.spec.Spec("mpich").concretized().satisfies("@3.0.3")
with pytest.raises(spack.config.ConfigError, match="not a list"): with pytest.raises(spack.config.ConfigError, match="not a list"):
config("change", "packages:mpich:require:~debug") config("change", "packages:mpich:require:~debug")