summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn W. Parent <45471568+johnwparent@users.noreply.github.com>2023-09-01 14:05:02 -0400
committerGitHub <noreply@github.com>2023-09-01 11:05:02 -0700
commitb72a268bc565d370bd64589e86929acfd73c08a1 (patch)
treeed532b6e9761fc77f46e8987ca443c2151f015e3
parent818195a3bd19a916c73f66695fb3bd7845f94a7d (diff)
downloadspack-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.py31
-rw-r--r--lib/spack/spack/test/config.py6
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):