diff options
author | John W. Parent <45471568+johnwparent@users.noreply.github.com> | 2023-09-01 14:05:02 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-01 11:05:02 -0700 |
commit | b72a268bc565d370bd64589e86929acfd73c08a1 (patch) | |
tree | ed532b6e9761fc77f46e8987ca443c2151f015e3 | |
parent | 818195a3bd19a916c73f66695fb3bd7845f94a7d (diff) | |
download | spack-b72a268bc565d370bd64589e86929acfd73c08a1.tar.gz spack-b72a268bc565d370bd64589e86929acfd73c08a1.tar.bz2 spack-b72a268bc565d370bd64589e86929acfd73c08a1.tar.xz spack-b72a268bc565d370bd64589e86929acfd73c08a1.zip |
"spack config add": allow values with a ":" (#39279)
If you wanted to set a configuration option like
`config:install_tree:root` to "C:/path/to/config.yaml", Spack had
trouble parsing this because of the ":" in the value. This adds
logic to allow using quotes to enclose the value, so you can add
`config:install_tree:root:"C:/path/to/config.yaml"`.
Configuration keys should never contain a quote character, so the
presence of any quote is taken to mean that the rest of the string
is specifying the value.
-rw-r--r-- | lib/spack/spack/config.py | 31 | ||||
-rw-r--r-- | lib/spack/spack/test/config.py | 6 |
2 files changed, 30 insertions, 7 deletions
diff --git a/lib/spack/spack/config.py b/lib/spack/spack/config.py index b3fb5648ac..ea9d12d2bd 100644 --- a/lib/spack/spack/config.py +++ b/lib/spack/spack/config.py @@ -863,6 +863,7 @@ def add(fullpath, scope=None): has_existing_value = True path = "" override = False + value = syaml.load_config(components[-1]) for idx, name in enumerate(components[:-1]): # First handle double colons in constructing path colon = "::" if override else ":" if path else "" @@ -883,14 +884,14 @@ def add(fullpath, scope=None): existing = get_valid_type(path) # construct value from this point down - value = syaml.load_config(components[-1]) for component in reversed(components[idx + 1 : -1]): value = {component: value} break + if override: + path += "::" + if has_existing_value: - path, _, value = fullpath.rpartition(":") - value = syaml.load_config(value) existing = get(path, scope=scope) # append values to lists @@ -1231,11 +1232,17 @@ def merge_yaml(dest, source, prepend=False, append=False): return copy.copy(source) -# -# Process a path argument to config.set() that may contain overrides ('::' or -# trailing ':') -# def process_config_path(path): + """Process a path argument to config.set() that may contain overrides ('::' or + trailing ':') + + Note: quoted value path components will be processed as a single value (escaping colons) + quoted path components outside of the value will be considered ill formed and will + raise. + e.g. `this:is:a:path:'value:with:colon'` will yield: + + [this, is, a, path, value:with:colon] + """ result = [] if path.startswith(":"): raise syaml.SpackYAMLError("Illegal leading `:' in path `{0}'".format(path), "") @@ -1262,6 +1269,16 @@ def process_config_path(path): front = syaml.syaml_str(front) front.append = True + quote = "['\"]" + not_quote = "[^'\"]" + + if re.match(f"^{quote}", path): + m = re.match(rf"^{quote}({not_quote}+){quote}$", path) + if not m: + raise ValueError("Quotes indicate value, but there are additional path entries") + result.append(m.group(1)) + break + result.append(front) return result diff --git a/lib/spack/spack/test/config.py b/lib/spack/spack/test/config.py index d3b5a544ba..1dbbba9cde 100644 --- a/lib/spack/spack/test/config.py +++ b/lib/spack/spack/test/config.py @@ -277,6 +277,12 @@ def test_add_config_path(mutable_config): compilers = spack.config.get("packages")["all"]["compiler"] assert "gcc" in compilers + # Try with an escaped colon + path = 'config:install_tree:root:"C:/path/to/config.yaml"' + spack.config.add(path) + set_value = spack.config.get("config")["install_tree"]["root"] + assert set_value == "C:/path/to/config.yaml" + @pytest.mark.regression("17543,23259") def test_add_config_path_with_enumerated_type(mutable_config): |