summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/cmd/config.py52
-rw-r--r--lib/spack/spack/config.py4
-rw-r--r--lib/spack/spack/test/cmd/config.py29
3 files changed, 43 insertions, 42 deletions
diff --git a/lib/spack/spack/cmd/config.py b/lib/spack/spack/cmd/config.py
index e7d459ff77..e7b859adb7 100644
--- a/lib/spack/spack/cmd/config.py
+++ b/lib/spack/spack/cmd/config.py
@@ -5,6 +5,7 @@
import collections
import os
import shutil
+import sys
from typing import List
import llnl.util.filesystem as fs
@@ -48,6 +49,7 @@ def setup_parser(subparser):
blame_parser.add_argument(
"section",
help="configuration section to print\n\noptions: %(choices)s",
+ nargs="?",
metavar="section",
choices=spack.config.SECTION_SCHEMAS,
)
@@ -131,32 +133,50 @@ def _get_scope_and_section(args):
return scope, section
+def print_configuration(args, *, blame: bool) -> None:
+ if args.scope and args.section is None:
+ tty.die(f"the argument --scope={args.scope} requires specifying a section.")
+
+ if args.section is not None:
+ spack.config.CONFIG.print_section(args.section, blame=blame, scope=args.scope)
+ return
+
+ print_flattened_configuration(blame=blame)
+
+
+def print_flattened_configuration(*, blame: bool) -> None:
+ """Prints to stdout a flattened version of the configuration.
+
+ Args:
+ blame: if True, shows file provenance for each entry in the configuration.
+ """
+ env = ev.active_environment()
+ if env is not None:
+ pristine = env.manifest.pristine_yaml_content
+ flattened = pristine.copy()
+ flattened[spack.schema.env.TOP_LEVEL_KEY] = pristine[spack.schema.env.TOP_LEVEL_KEY].copy()
+ else:
+ flattened = syaml.syaml_dict()
+ flattened[spack.schema.env.TOP_LEVEL_KEY] = syaml.syaml_dict()
+
+ for config_section in spack.config.SECTION_SCHEMAS:
+ current = spack.config.get(config_section)
+ flattened[spack.schema.env.TOP_LEVEL_KEY][config_section] = current
+ syaml.dump_config(flattened, stream=sys.stdout, default_flow_style=False, blame=blame)
+
+
def config_get(args):
"""Dump merged YAML configuration for a specific section.
With no arguments and an active environment, print the contents of
the environment's manifest file (spack.yaml).
"""
- scope, section = _get_scope_and_section(args)
-
- if section is not None:
- spack.config.CONFIG.print_section(section)
-
- elif scope and scope.startswith("env:"):
- config_file = spack.config.CONFIG.get_config_filename(scope, section)
- if os.path.exists(config_file):
- with open(config_file) as f:
- print(f.read())
- else:
- tty.die("environment has no %s file" % ev.manifest_name)
-
- else:
- tty.die("`spack config get` requires a section argument or an active environment.")
+ print_configuration(args, blame=False)
def config_blame(args):
"""Print out line-by-line blame of merged YAML."""
- spack.config.CONFIG.print_section(args.section, blame=True)
+ print_configuration(args, blame=True)
def config_edit(args):
diff --git a/lib/spack/spack/config.py b/lib/spack/spack/config.py
index eff978718c..b661f4dc48 100644
--- a/lib/spack/spack/config.py
+++ b/lib/spack/spack/config.py
@@ -699,11 +699,11 @@ class Configuration:
"""Iterate over scopes in this configuration."""
yield from self.scopes.values()
- def print_section(self, section: str, blame: bool = False) -> None:
+ def print_section(self, section: str, blame: bool = False, *, scope=None) -> None:
"""Print a configuration to stdout."""
try:
data = syaml.syaml_dict()
- data[section] = self.get_config(section)
+ data[section] = self.get_config(section, scope=scope)
syaml.dump_config(data, stream=sys.stdout, default_flow_style=False, blame=blame)
except (syaml.SpackYAMLError, OSError) as e:
raise ConfigError(f"cannot read '{section}' configuration") from e
diff --git a/lib/spack/spack/test/cmd/config.py b/lib/spack/spack/test/cmd/config.py
index 7247ce9753..bec9db3881 100644
--- a/lib/spack/spack/test/cmd/config.py
+++ b/lib/spack/spack/test/cmd/config.py
@@ -91,15 +91,10 @@ def test_config_edit(mutable_config, working_env):
def test_config_get_gets_spack_yaml(mutable_mock_env_path):
- config("get", fail_on_error=False)
- assert config.returncode == 1
-
with ev.create("test") as env:
assert "mpileaks" not in config("get")
-
env.add("mpileaks")
env.write()
-
assert "mpileaks" in config("get")
@@ -122,11 +117,6 @@ def test_config_edit_fails_correctly_with_no_env(mutable_mock_env_path):
assert "requires a section argument or an active environment" in output
-def test_config_get_fails_correctly_with_no_env(mutable_mock_env_path):
- output = config("get", fail_on_error=False)
- assert "requires a section argument or an active environment" in output
-
-
def test_config_list():
output = config("list")
assert "compilers" in output
@@ -470,7 +460,6 @@ def test_config_add_to_env(mutable_empty_config, mutable_mock_env_path):
expected = """ config:
dirty: true
-
"""
assert expected in output
@@ -497,29 +486,21 @@ spack: # comment
config("add", "config:dirty:true")
output = config("get")
- expected = manifest
- expected += """ config:
- dirty: true
-
-"""
- assert output == expected
+ assert "# comment" in output
+ assert "dirty: true" in output
def test_config_remove_from_env(mutable_empty_config, mutable_mock_env_path):
env("create", "test")
-
with ev.read("test"):
config("add", "config:dirty:true")
+ output = config("get")
+ assert "dirty: true" in output
with ev.read("test"):
config("rm", "config:dirty")
output = config("get")
-
- expected = ev.default_manifest_yaml()
- expected += """ config: {}
-
-"""
- assert output == expected
+ assert "dirty: true" not in output
def test_config_update_config(config_yaml_v015):