environment.py: fix excessive re-reads (#43746)
This commit is contained in:
parent
39888d4df6
commit
44cb4eca93
3 changed files with 33 additions and 28 deletions
|
@ -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
|
||||||
|
|
|
@ -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."""
|
||||||
|
|
|
@ -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")
|
||||||
|
|
Loading…
Reference in a new issue