diff options
author | Todd Gamblin <gamblin2@llnl.gov> | 2021-04-08 07:37:16 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-08 16:37:16 +0200 |
commit | 19b6d3589a285031e410aa08e09655c60f5e17a4 (patch) | |
tree | a1f932b563d12c51b2c2cf38e26a3a3488a7acc2 | |
parent | f27fefc3c1fc26f1c6aad1d1a125a522078ba779 (diff) | |
download | spack-19b6d3589a285031e410aa08e09655c60f5e17a4.tar.gz spack-19b6d3589a285031e410aa08e09655c60f5e17a4.tar.bz2 spack-19b6d3589a285031e410aa08e09655c60f5e17a4.tar.xz spack-19b6d3589a285031e410aa08e09655c60f5e17a4.zip |
bugfix: `spack config blame` should print all lines of config (#22598)
* bugfix: fix representation of null in spack_yaml output
Nulls were previously printed differently by `spack config blame config`
and `spack config get config`. Fix this in the `spack_yaml` dumpers.
* bugfix: `spack config blame` should print all lines of config
`spack config blame` was not printing all lines of configuration because
there were no annotations for empty lines in the YAML dump output. Fix
this by removing empty lines.
-rw-r--r-- | lib/spack/spack/test/util/spack_yaml.py | 28 | ||||
-rw-r--r-- | lib/spack/spack/util/spack_yaml.py | 23 |
2 files changed, 44 insertions, 7 deletions
diff --git a/lib/spack/spack/test/util/spack_yaml.py b/lib/spack/spack/test/util/spack_yaml.py index 530226ad8d..34a923093f 100644 --- a/lib/spack/spack/test/util/spack_yaml.py +++ b/lib/spack/spack/test/util/spack_yaml.py @@ -65,3 +65,31 @@ def test_config_blame_with_override(config): check_blame('verify_ssl', config_file, 13) check_blame('checksum', config_file, 14) check_blame('dirty', config_file, 15) + + +def test_config_blame_defaults(): + """check blame for an element from an override scope""" + files = {} + + def get_file_lines(filename): + if filename not in files: + with open(filename, "r") as f: + files[filename] = [""] + f.read().split("\n") + return files[filename] + + config_blame = config_cmd("blame", "config") + for line in config_blame.split("\n"): + # currently checking only simple lines with dict keys + match = re.match(r"^([^:]+):(\d+)\s+([^:]+):\s+(.*)", line) + + # check that matches are on the lines they say they are + if match: + filename, line, key, val = match.groups() + line = int(line) + + if val.lower() in ("true", "false"): + val = val.lower() + + lines = get_file_lines(filename) + assert key in lines[line] + assert val in lines[line] diff --git a/lib/spack/spack/util/spack_yaml.py b/lib/spack/spack/util/spack_yaml.py index e27c48860b..24eea88b77 100644 --- a/lib/spack/spack/util/spack_yaml.py +++ b/lib/spack/spack/util/spack_yaml.py @@ -13,6 +13,7 @@ """ import ctypes +import re import sys from typing import List # novm @@ -185,6 +186,12 @@ class OrderedLineDumper(RoundTripDumper): """Make the dumper NEVER print YAML aliases.""" return True + def represent_data(self, data): + result = super(OrderedLineDumper, self).represent_data(data) + if data is None: + result.value = syaml_str("null") + return result + def represent_str(self, data): if hasattr(data, 'override') and data.override: data = data + ':' @@ -262,19 +269,18 @@ class LineAnnotationDumper(OrderedLineDumper): def represent_data(self, data): """Force syaml_str to be passed through with marks.""" result = super(LineAnnotationDumper, self).represent_data(data) - if isinstance(result.value, string_types): + if data is None: + result.value = syaml_str("null") + elif isinstance(result.value, string_types): result.value = syaml_str(data) if markable(result.value): mark(result.value, data) return result - def write_stream_start(self): - super(LineAnnotationDumper, self).write_stream_start() - _annotations.append(colorize('@K{---}')) - def write_line_break(self): super(LineAnnotationDumper, self).write_line_break() - if not self.saved: + if self.saved is None: + _annotations.append(colorize('@K{---}')) return # append annotations at the end of each line @@ -322,7 +328,10 @@ def dump_annotated(data, stream=None, *args, **kwargs): sio = StringIO() yaml.dump(data, sio, *args, **kwargs) - lines = sio.getvalue().rstrip().split('\n') + + # write_line_break() is not called by YAML for empty lines, so we + # skip empty lines here with \n+. + lines = re.split(r"\n+", sio.getvalue().rstrip()) getvalue = None if stream is None: |